diff --git a/app/Main.hs b/app/Main.hs index 7ca940f..5a8a8f9 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -2,6 +2,7 @@ module Main where import Data.Picture import System.Environment import Data.Either + import Numeric.LinearAlgebra (rows, cols) data Options = Options { file :: FilePath , output :: FilePath @@ -13,6 +14,7 @@ module Main where , argGamma :: Int , argBrightness :: Double , argCompress :: Int + , argScale :: Double } opts = Options { file = "" @@ -25,6 +27,7 @@ module Main where , argGamma = 1 , argBrightness = 0 , argCompress = 0 + , argScale = 1 } main :: IO () @@ -42,6 +45,7 @@ module Main where putStrLn " --rotate - rotate image by n degrees" putStrLn " --grayscale - turn the image grayscale" putStrLn " --invert - invert (negative) the image" + putStrLn " --scale - scale the image using nearest-neighbor interpolation" putStrLn " --compress - approximate the (width - n)-th rank of image using SVD, note: this is not size compression, a number between 0 (no compression) and image width (full compression)" putStrLn " --output - output name, defaults to output.png" else do @@ -60,6 +64,7 @@ module Main where . brightness (argBrightness options) . conditionalFn grayscale (argGrayscale options) . conditionalFn invert (argInvert options) + . scale (argScale options) . compress (argCompress options) $ p writePicturePng (output options) edited @@ -79,6 +84,7 @@ module Main where parseArgs ("--brightness":n:rest) opts = parseArgs rest (opts { argBrightness = read n }) parseArgs ("--gamma":n:rest) opts = parseArgs rest (opts { argGamma = read n }) parseArgs ("--compress":n:rest) opts = parseArgs rest (opts { argCompress = read n }) + parseArgs ("--scale":n:rest) opts = parseArgs rest (opts { argScale = read n }) parseArgs ("--output":n:rest) opts = parseArgs rest (opts { output = n }) parseArgs (name:rest) opts = parseArgs rest (opts { file = name }) diff --git a/picedit.cabal b/picedit.cabal index 615b27e..01e6774 100644 --- a/picedit.cabal +++ b/picedit.cabal @@ -1,5 +1,5 @@ name: picedit -version: 0.2.0.0 +version: 0.2.1.0 synopsis: simple image manipulation functions description: Simple set of functions for image manipulation: contrast, brightnesss, rotation, etc. homepage: https://github.com/mdibaiee/picedit#readme @@ -16,10 +16,10 @@ cabal-version: >=1.10 library hs-source-dirs: src exposed-modules: Data.Picture - build-depends: base >= 4.7 && < 5, - JuicyPixels >= 3.2.8 && < 3.3, - hmatrix >= 0.17.0.2 && < 0.19, - vector >= 0.11.0.0 && < 0.13 + build-depends: base >= 4.7 && < 5 + , JuicyPixels >= 3.2.8 && < 3.3 + , hmatrix >= 0.17.0.2 && < 0.19 + , vector >= 0.11.0.0 && < 0.13 default-language: Haskell2010 executable picedit @@ -29,6 +29,7 @@ executable picedit build-depends: base , picedit , cli >= 0.1.2 && < 0.2 + , hmatrix >= 0.17.0.2 && < 0.19 default-language: Haskell2010 source-repository head diff --git a/src/Data/Picture.hs b/src/Data/Picture.hs index 2fc4d9c..9a758e1 100644 --- a/src/Data/Picture.hs +++ b/src/Data/Picture.hs @@ -22,6 +22,8 @@ module Data.Picture ( Picture , invert , compress , embed + , resize + , Data.Picture.scale -- * Converting between Image and Picture , fromImage , toImage @@ -170,5 +172,28 @@ module Data.Picture ( Picture f b lm = (b * (cmap (1-) scaledAlpha)) + (lm * scaledAlpha) maxAlpha = (rows ba> Picture -> Picture + resize (sWidth, sHeight) (r, g, b, a) = (f r, f g, f b, f a) + where + initial = vector [0..fromIntegral sWidth * fromIntegral sHeight - 1] + (width, height) = (rows r, cols r) + (xRatio, yRatio) = (fromIntegral width / fromIntegral sWidth, fromIntegral height / fromIntegral sHeight) + f m = tr $ reshape sWidth $ V.map replace initial + where + v = flatten (tr m) + replace index = + let (x, y) = (fromIntegral $ floor index `mod` sWidth, fromIntegral . floor $ index / fromIntegral sWidth) + (px, py) = (floor $ x * xRatio, floor $ y * yRatio) + in v ! (py * width + px) + + -- | Scale an image using the resize function + scale :: Double -> Picture -> Picture + scale 1 p = p + scale s (r, g, b, a) = resize (floor $ s * width, floor $ s * height) (r, g, b, a) + where + (width, height) = (fromIntegral $ rows r, fromIntegral $ cols r) + + bound (l, u) x = max l $ min u x pixelBound = bound (0, 255)