feat(resize): resize/scale using nearest-neighbor
This commit is contained in:
parent
0f40936c98
commit
529d503204
@ -2,6 +2,7 @@ module Main where
|
|||||||
import Data.Picture
|
import Data.Picture
|
||||||
import System.Environment
|
import System.Environment
|
||||||
import Data.Either
|
import Data.Either
|
||||||
|
import Numeric.LinearAlgebra (rows, cols)
|
||||||
|
|
||||||
data Options = Options { file :: FilePath
|
data Options = Options { file :: FilePath
|
||||||
, output :: FilePath
|
, output :: FilePath
|
||||||
@ -13,6 +14,7 @@ module Main where
|
|||||||
, argGamma :: Int
|
, argGamma :: Int
|
||||||
, argBrightness :: Double
|
, argBrightness :: Double
|
||||||
, argCompress :: Int
|
, argCompress :: Int
|
||||||
|
, argScale :: Double
|
||||||
}
|
}
|
||||||
|
|
||||||
opts = Options { file = ""
|
opts = Options { file = ""
|
||||||
@ -25,6 +27,7 @@ module Main where
|
|||||||
, argGamma = 1
|
, argGamma = 1
|
||||||
, argBrightness = 0
|
, argBrightness = 0
|
||||||
, argCompress = 0
|
, argCompress = 0
|
||||||
|
, argScale = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
@ -42,6 +45,7 @@ module Main where
|
|||||||
putStrLn " --rotate <n> - rotate image by n degrees"
|
putStrLn " --rotate <n> - rotate image by n degrees"
|
||||||
putStrLn " --grayscale - turn the image grayscale"
|
putStrLn " --grayscale - turn the image grayscale"
|
||||||
putStrLn " --invert - invert (negative) the image"
|
putStrLn " --invert - invert (negative) the image"
|
||||||
|
putStrLn " --scale <n> - scale the image using nearest-neighbor interpolation"
|
||||||
putStrLn " --compress <n> - 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 " --compress <n> - 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 <filename> - output name, defaults to output.png"
|
putStrLn " --output <filename> - output name, defaults to output.png"
|
||||||
else do
|
else do
|
||||||
@ -60,6 +64,7 @@ module Main where
|
|||||||
. brightness (argBrightness options)
|
. brightness (argBrightness options)
|
||||||
. conditionalFn grayscale (argGrayscale options)
|
. conditionalFn grayscale (argGrayscale options)
|
||||||
. conditionalFn invert (argInvert options)
|
. conditionalFn invert (argInvert options)
|
||||||
|
. scale (argScale options)
|
||||||
. compress (argCompress options) $ p
|
. compress (argCompress options) $ p
|
||||||
writePicturePng (output options) edited
|
writePicturePng (output options) edited
|
||||||
|
|
||||||
@ -79,6 +84,7 @@ module Main where
|
|||||||
parseArgs ("--brightness":n:rest) opts = parseArgs rest (opts { argBrightness = read n })
|
parseArgs ("--brightness":n:rest) opts = parseArgs rest (opts { argBrightness = read n })
|
||||||
parseArgs ("--gamma":n:rest) opts = parseArgs rest (opts { argGamma = 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 ("--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 ("--output":n:rest) opts = parseArgs rest (opts { output = n })
|
||||||
parseArgs (name:rest) opts = parseArgs rest (opts { file = name })
|
parseArgs (name:rest) opts = parseArgs rest (opts { file = name })
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
name: picedit
|
name: picedit
|
||||||
version: 0.2.0.0
|
version: 0.2.1.0
|
||||||
synopsis: simple image manipulation functions
|
synopsis: simple image manipulation functions
|
||||||
description: Simple set of functions for image manipulation: contrast, brightnesss, rotation, etc.
|
description: Simple set of functions for image manipulation: contrast, brightnesss, rotation, etc.
|
||||||
homepage: https://github.com/mdibaiee/picedit#readme
|
homepage: https://github.com/mdibaiee/picedit#readme
|
||||||
@ -16,10 +16,10 @@ cabal-version: >=1.10
|
|||||||
library
|
library
|
||||||
hs-source-dirs: src
|
hs-source-dirs: src
|
||||||
exposed-modules: Data.Picture
|
exposed-modules: Data.Picture
|
||||||
build-depends: base >= 4.7 && < 5,
|
build-depends: base >= 4.7 && < 5
|
||||||
JuicyPixels >= 3.2.8 && < 3.3,
|
, JuicyPixels >= 3.2.8 && < 3.3
|
||||||
hmatrix >= 0.17.0.2 && < 0.19,
|
, hmatrix >= 0.17.0.2 && < 0.19
|
||||||
vector >= 0.11.0.0 && < 0.13
|
, vector >= 0.11.0.0 && < 0.13
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
|
|
||||||
executable picedit
|
executable picedit
|
||||||
@ -29,6 +29,7 @@ executable picedit
|
|||||||
build-depends: base
|
build-depends: base
|
||||||
, picedit
|
, picedit
|
||||||
, cli >= 0.1.2 && < 0.2
|
, cli >= 0.1.2 && < 0.2
|
||||||
|
, hmatrix >= 0.17.0.2 && < 0.19
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
|
|
||||||
source-repository head
|
source-repository head
|
||||||
|
@ -22,6 +22,8 @@ module Data.Picture ( Picture
|
|||||||
, invert
|
, invert
|
||||||
, compress
|
, compress
|
||||||
, embed
|
, embed
|
||||||
|
, resize
|
||||||
|
, Data.Picture.scale
|
||||||
-- * Converting between Image and Picture
|
-- * Converting between Image and Picture
|
||||||
, fromImage
|
, fromImage
|
||||||
, toImage
|
, toImage
|
||||||
@ -170,5 +172,28 @@ module Data.Picture ( Picture
|
|||||||
f b lm = (b * (cmap (1-) scaledAlpha)) + (lm * scaledAlpha)
|
f b lm = (b * (cmap (1-) scaledAlpha)) + (lm * scaledAlpha)
|
||||||
maxAlpha = (rows ba><cols ba) $ zipWith max (toList . flatten $ ba) (toList . flatten . fit $ la)
|
maxAlpha = (rows ba><cols ba) $ zipWith max (toList . flatten $ ba) (toList . flatten . fit $ la)
|
||||||
|
|
||||||
|
-- | Resize an image using nearest-neighbor interpolation
|
||||||
|
resize :: (Int, Int) -> 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
|
bound (l, u) x = max l $ min u x
|
||||||
pixelBound = bound (0, 255)
|
pixelBound = bound (0, 255)
|
||||||
|
Loading…
Reference in New Issue
Block a user