module Codec.Picture (
readImage
, decodeImage
, pixelMap
, generateImage
, generateFoldImage
, saveBmpImage
, saveJpgImage
, savePngImage
, BmpEncodable
, writeBitmap
, encodeBitmap
, readBitmap
, decodeBitmap
, encodeDynamicBitmap
, writeDynamicBitmap
, readJpeg
, decodeJpeg
, encodeJpeg
, encodeJpegAtQuality
, PngSavable( .. )
, readPng
, decodePng
, writePng
, encodeDynamicPng
, writeDynamicPng
, Image( .. )
, DynamicImage( .. )
, Pixel( .. )
, Pixel8
, PixelYA8( .. )
, PixelRGB8( .. )
, PixelRGBA8( .. )
, PixelYCbCr8( .. )
) where
import Control.Applicative( (<$>) )
import Control.DeepSeq( NFData, deepseq )
import Control.Exception( catch, IOException )
import Codec.Picture.Bitmap( BmpEncodable, decodeBitmap
, writeBitmap, encodeBitmap
, encodeDynamicBitmap, writeDynamicBitmap )
import Codec.Picture.Jpg( decodeJpeg, encodeJpeg, encodeJpegAtQuality )
import Codec.Picture.Png( PngSavable( .. ), decodePng, writePng
, encodeDynamicPng , writeDynamicPng )
import Codec.Picture.Saving
import Codec.Picture.Types
import System.IO ( withFile, IOMode(ReadMode) )
import Prelude hiding(catch)
import qualified Data.ByteString as B
eitherLoad :: c -> [(String, c -> Either String b)] -> Either String b
eitherLoad v = inner ""
where inner errAcc [] = Left $ "Cannot load file\n" ++ errAcc
inner errAcc ((hdr, f) : rest) = case f v of
Left err -> inner (errAcc ++ hdr ++ " " ++ err ++ "\n") rest
Right rez -> Right rez
withImageDecoder :: (NFData a)
=> (B.ByteString -> Either String a) -> FilePath
-> IO (Either String a)
withImageDecoder decoder path = catch doit
(\e -> return . Left $ show (e :: IOException))
where doit = withFile path ReadMode $ \h ->
force . decoder <$> B.hGetContents h
force x = x `deepseq` x
readImage :: FilePath -> IO (Either String DynamicImage)
readImage = withImageDecoder decodeImage
decodeImage :: B.ByteString -> Either String DynamicImage
decodeImage str = eitherLoad str [("Jpeg", decodeJpeg)
,("PNG", decodePng)
,("Bitmap", decodeBitmap)
]
readPng :: FilePath -> IO (Either String DynamicImage)
readPng = withImageDecoder decodePng
readJpeg :: FilePath -> IO (Either String DynamicImage)
readJpeg = withImageDecoder decodeJpeg
readBitmap :: FilePath -> IO (Either String DynamicImage)
readBitmap = withImageDecoder decodeBitmap
saveJpgImage :: Int -> String -> DynamicImage -> IO ()
saveJpgImage quality path img = B.writeFile path $ imageToJpg quality img
savePngImage :: String -> DynamicImage -> IO ()
savePngImage path img = B.writeFile path $ imageToPng img
saveBmpImage :: String -> DynamicImage -> IO ()
saveBmpImage path img = B.writeFile path $ imageToBitmap img