picedit/app/Main.hs
2017-02-03 21:57:48 +03:30

91 lines
3.8 KiB
Haskell

module Main where
import Data.Picture
import System.Environment
import Data.Either
import Numeric.LinearAlgebra (rows, cols)
data Options = Options { file :: FilePath
, output :: FilePath
, argInvert :: Bool
, argGrayscale :: Bool
, argRotate :: Double
, argFade :: Double
, argContrast :: Double
, argGamma :: Int
, argBrightness :: Double
, argCompress :: Int
, argScale :: Double
}
opts = Options { file = ""
, output = "output.png"
, argInvert = False
, argGrayscale = False
, argRotate = 0
, argFade = 100
, argContrast = 0
, argGamma = 1
, argBrightness = 0
, argCompress = 0
, argScale = 1
}
main :: IO ()
main = do
args <- getArgs
if null args
then do
putStrLn "Usage: picedit <input> [OPTIONS]"
putStrLn "Options:"
putStrLn " --contrast <n> - a number between -255 and 255"
putStrLn " --brightness <n> - a number between -255 and 255"
putStrLn " --gamma <n>"
putStrLn " --fade <n> - a number between 0 and 100"
putStrLn " --rotate <n> - rotate image by n degrees"
putStrLn " --grayscale - turn the image grayscale"
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 " --output <filename> - output name, defaults to output.png"
else do
let options = parseArgs args opts
pic <- readPicture (file options)
Right other <- readPicture ("output.png")
case pic of
Left err -> print err
Right p -> do
let edited = rotate (argRotate options) Nothing
. fade (argFade options / 100)
. contrast (argContrast options)
. gamma (argGamma options)
. brightness (argBrightness options)
. conditionalFn grayscale (argGrayscale options)
. conditionalFn invert (argInvert options)
. scale (argScale options)
. compress (argCompress options) $ p
writePicturePng (output options) edited
return ()
where
conditionalFn f True = f
conditionalFn f False = id
parseArgs :: [String] -> Options -> Options
parseArgs [] opts = opts
parseArgs ("--invert":rest) opts = parseArgs rest (opts { argInvert = True })
parseArgs ("--grayscale":rest) opts = parseArgs rest (opts { argGrayscale = True })
parseArgs ("--rotate":n:rest) opts = parseArgs rest (opts { argRotate = read n })
parseArgs ("--fade":n:rest) opts = parseArgs rest (opts { argFade = read n })
parseArgs ("--contrast":n:rest) opts = parseArgs rest (opts { argContrast = 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 ("--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 })