|
Packit |
c600df |
{-# LANGUAGE TypeFamilies #-}
|
|
Packit |
c600df |
{-# LANGUAGE CPP #-}
|
|
Packit |
c600df |
-- | Helper functions to save dynamic images to other file format
|
|
Packit |
c600df |
-- with automatic color space/sample format conversion done automatically.
|
|
Packit |
c600df |
module Codec.Picture.Saving( imageToJpg
|
|
Packit |
c600df |
, imageToPng
|
|
Packit |
c600df |
, imageToGif
|
|
Packit |
c600df |
, imageToBitmap
|
|
Packit |
c600df |
, imageToTiff
|
|
Packit |
c600df |
, imageToRadiance
|
|
Packit |
c600df |
, imageToTga
|
|
Packit |
c600df |
) where
|
|
Packit |
c600df |
|
|
Packit |
c600df |
#if !MIN_VERSION_base(4,8,0)
|
|
Packit |
c600df |
import Data.Monoid( mempty )
|
|
Packit |
c600df |
#endif
|
|
Packit |
c600df |
|
|
Packit |
c600df |
import Data.Bits( unsafeShiftR )
|
|
Packit |
c600df |
import Data.Word( Word8, Word16 )
|
|
Packit |
c600df |
import qualified Data.ByteString.Lazy as L
|
|
Packit |
c600df |
import Codec.Picture.Bitmap
|
|
Packit |
c600df |
import Codec.Picture.Jpg
|
|
Packit |
c600df |
import Codec.Picture.Png
|
|
Packit |
c600df |
import Codec.Picture.Gif
|
|
Packit |
c600df |
import Codec.Picture.ColorQuant
|
|
Packit |
c600df |
import Codec.Picture.HDR
|
|
Packit |
c600df |
import Codec.Picture.Types
|
|
Packit |
c600df |
import Codec.Picture.Tiff
|
|
Packit |
c600df |
import Codec.Picture.Tga
|
|
Packit |
c600df |
|
|
Packit |
c600df |
import qualified Data.Vector.Storable as V
|
|
Packit |
c600df |
|
|
Packit |
c600df |
componentToLDR :: Float -> Word8
|
|
Packit |
c600df |
componentToLDR = truncate . (255 *) . min 1.0 . max 0.0
|
|
Packit |
c600df |
|
|
Packit |
c600df |
toStandardDef :: Image PixelRGBF -> Image PixelRGB8
|
|
Packit |
c600df |
toStandardDef = pixelMap pixelConverter
|
|
Packit |
c600df |
where pixelConverter (PixelRGBF rf gf bf) = PixelRGB8 r g b
|
|
Packit |
c600df |
where r = componentToLDR rf
|
|
Packit |
c600df |
g = componentToLDR gf
|
|
Packit |
c600df |
b = componentToLDR bf
|
|
Packit |
c600df |
|
|
Packit |
c600df |
greyScaleToStandardDef :: Image PixelF -> Image Pixel8
|
|
Packit |
c600df |
greyScaleToStandardDef = pixelMap componentToLDR
|
|
Packit |
c600df |
|
|
Packit |
c600df |
from16to8 :: ( PixelBaseComponent source ~ Word16
|
|
Packit |
c600df |
, PixelBaseComponent dest ~ Word8 )
|
|
Packit |
c600df |
=> Image source -> Image dest
|
|
Packit |
c600df |
from16to8 Image { imageWidth = w, imageHeight = h
|
|
Packit |
c600df |
, imageData = arr } = Image w h transformed
|
|
Packit |
c600df |
where transformed = V.map toWord8 arr
|
|
Packit |
c600df |
toWord8 v = fromIntegral (v `unsafeShiftR` 8)
|
|
Packit |
c600df |
|
|
Packit |
c600df |
from16toFloat :: ( PixelBaseComponent source ~ Word16
|
|
Packit |
c600df |
, PixelBaseComponent dest ~ Float )
|
|
Packit |
c600df |
=> Image source -> Image dest
|
|
Packit |
c600df |
from16toFloat Image { imageWidth = w, imageHeight = h
|
|
Packit |
c600df |
, imageData = arr } = Image w h transformed
|
|
Packit |
c600df |
where transformed = V.map toWord8 arr
|
|
Packit |
c600df |
toWord8 v = fromIntegral v / 65536.0
|
|
Packit |
c600df |
|
|
Packit |
c600df |
-- | This function will try to do anything to encode an image
|
|
Packit |
c600df |
-- as RADIANCE, make all color conversion and such. Equivalent
|
|
Packit |
c600df |
-- of 'decodeImage' for radiance encoding
|
|
Packit |
c600df |
imageToRadiance :: DynamicImage -> L.ByteString
|
|
Packit |
c600df |
imageToRadiance (ImageCMYK8 img) =
|
|
Packit |
c600df |
imageToRadiance . ImageRGB8 $ convertImage img
|
|
Packit |
c600df |
imageToRadiance (ImageCMYK16 img) =
|
|
Packit |
c600df |
imageToRadiance . ImageRGB16 $ convertImage img
|
|
Packit |
c600df |
imageToRadiance (ImageYCbCr8 img) =
|
|
Packit |
c600df |
imageToRadiance . ImageRGB8 $ convertImage img
|
|
Packit |
c600df |
imageToRadiance (ImageRGB8 img) =
|
|
Packit |
c600df |
imageToRadiance . ImageRGBF $ promoteImage img
|
|
Packit |
c600df |
imageToRadiance (ImageRGBF img) = encodeHDR img
|
|
Packit |
c600df |
imageToRadiance (ImageRGBA8 img) =
|
|
Packit |
c600df |
imageToRadiance . ImageRGBF . promoteImage $ dropAlphaLayer img
|
|
Packit |
c600df |
imageToRadiance (ImageY8 img) =
|
|
Packit |
c600df |
imageToRadiance . ImageRGB8 $ promoteImage img
|
|
Packit |
c600df |
imageToRadiance (ImageYF img) =
|
|
Packit |
c600df |
imageToRadiance . ImageRGBF $ promoteImage img
|
|
Packit |
c600df |
imageToRadiance (ImageYA8 img) =
|
|
Packit |
c600df |
imageToRadiance . ImageRGB8 . promoteImage $ dropAlphaLayer img
|
|
Packit |
c600df |
imageToRadiance (ImageY16 img) =
|
|
Packit |
c600df |
imageToRadiance . ImageRGBF $ pixelMap toRgbf img
|
|
Packit |
c600df |
where toRgbf v = PixelRGBF val val val
|
|
Packit |
c600df |
where val = fromIntegral v / 65536.0
|
|
Packit |
c600df |
|
|
Packit |
c600df |
imageToRadiance (ImageYA16 img) =
|
|
Packit |
c600df |
imageToRadiance . ImageRGBF $ pixelMap toRgbf img
|
|
Packit |
c600df |
where toRgbf (PixelYA16 v _) = PixelRGBF val val val
|
|
Packit |
c600df |
where val = fromIntegral v / 65536.0
|
|
Packit |
c600df |
imageToRadiance (ImageRGB16 img) =
|
|
Packit |
c600df |
imageToRadiance . ImageRGBF $ from16toFloat img
|
|
Packit |
c600df |
imageToRadiance (ImageRGBA16 img) =
|
|
Packit |
c600df |
imageToRadiance . ImageRGBF $ pixelMap toRgbf img
|
|
Packit |
c600df |
where toRgbf (PixelRGBA16 r g b _) = PixelRGBF (f r) (f g) (f b)
|
|
Packit |
c600df |
where f v = fromIntegral v / 65536.0
|
|
Packit |
c600df |
|
|
Packit |
c600df |
-- | This function will try to do anything to encode an image
|
|
Packit |
c600df |
-- as JPEG, make all color conversion and such. Equivalent
|
|
Packit |
c600df |
-- of 'decodeImage' for jpeg encoding
|
|
Packit |
c600df |
-- Save Y or YCbCr Jpeg only, all other colorspaces are converted.
|
|
Packit |
c600df |
-- To save a RGB or CMYK JPEG file, use the
|
|
Packit |
c600df |
-- 'Codec.Picture.Jpg.encodeDirectJpegAtQualityWithMetadata' function
|
|
Packit |
c600df |
imageToJpg :: Int -> DynamicImage -> L.ByteString
|
|
Packit |
c600df |
imageToJpg quality dynImage =
|
|
Packit |
c600df |
let encodeAtQuality = encodeJpegAtQuality (fromIntegral quality)
|
|
Packit |
c600df |
encodeWithMeta = encodeDirectJpegAtQualityWithMetadata (fromIntegral quality) mempty
|
|
Packit |
c600df |
in case dynImage of
|
|
Packit |
c600df |
ImageYCbCr8 img -> encodeAtQuality img
|
|
Packit |
c600df |
ImageCMYK8 img -> imageToJpg quality . ImageRGB8 $ convertImage img
|
|
Packit |
c600df |
ImageCMYK16 img -> imageToJpg quality . ImageRGB16 $ convertImage img
|
|
Packit |
c600df |
ImageRGB8 img -> encodeAtQuality (convertImage img)
|
|
Packit |
c600df |
ImageRGBF img -> imageToJpg quality . ImageRGB8 $ toStandardDef img
|
|
Packit |
c600df |
ImageRGBA8 img -> encodeAtQuality (convertImage $ dropAlphaLayer img)
|
|
Packit |
c600df |
ImageYF img -> imageToJpg quality . ImageY8 $ greyScaleToStandardDef img
|
|
Packit |
c600df |
ImageY8 img -> encodeWithMeta img
|
|
Packit |
c600df |
ImageYA8 img -> encodeWithMeta $ dropAlphaLayer img
|
|
Packit |
c600df |
ImageY16 img -> imageToJpg quality . ImageY8 $ from16to8 img
|
|
Packit |
c600df |
ImageYA16 img -> imageToJpg quality . ImageYA8 $ from16to8 img
|
|
Packit |
c600df |
ImageRGB16 img -> imageToJpg quality . ImageRGB8 $ from16to8 img
|
|
Packit |
c600df |
ImageRGBA16 img -> imageToJpg quality . ImageRGBA8 $ from16to8 img
|
|
Packit |
c600df |
|
|
Packit |
c600df |
-- | This function will try to do anything to encode an image
|
|
Packit |
c600df |
-- as PNG, make all color conversion and such. Equivalent
|
|
Packit |
c600df |
-- of 'decodeImage' for PNG encoding
|
|
Packit |
c600df |
imageToPng :: DynamicImage -> L.ByteString
|
|
Packit |
c600df |
imageToPng (ImageYCbCr8 img) = encodePng (convertImage img :: Image PixelRGB8)
|
|
Packit |
c600df |
imageToPng (ImageCMYK8 img) = encodePng (convertImage img :: Image PixelRGB8)
|
|
Packit |
c600df |
imageToPng (ImageCMYK16 img) = encodePng (convertImage img :: Image PixelRGB16)
|
|
Packit |
c600df |
imageToPng (ImageRGB8 img) = encodePng img
|
|
Packit |
c600df |
imageToPng (ImageRGBF img) = encodePng $ toStandardDef img
|
|
Packit |
c600df |
imageToPng (ImageRGBA8 img) = encodePng img
|
|
Packit |
c600df |
imageToPng (ImageY8 img) = encodePng img
|
|
Packit |
c600df |
imageToPng (ImageYF img) = encodePng $ greyScaleToStandardDef img
|
|
Packit |
c600df |
imageToPng (ImageYA8 img) = encodePng img
|
|
Packit |
c600df |
imageToPng (ImageY16 img) = encodePng img
|
|
Packit |
c600df |
imageToPng (ImageYA16 img) = encodePng img
|
|
Packit |
c600df |
imageToPng (ImageRGB16 img) = encodePng img
|
|
Packit |
c600df |
imageToPng (ImageRGBA16 img) = encodePng img
|
|
Packit |
c600df |
|
|
Packit |
c600df |
-- | This function will try to do anything to encode an image
|
|
Packit |
c600df |
-- as a Tiff, make all color conversion and such. Equivalent
|
|
Packit |
c600df |
-- of 'decodeImage' for Tiff encoding
|
|
Packit |
c600df |
imageToTiff :: DynamicImage -> L.ByteString
|
|
Packit |
c600df |
imageToTiff (ImageYCbCr8 img) = encodeTiff img
|
|
Packit |
c600df |
imageToTiff (ImageCMYK8 img) = encodeTiff img
|
|
Packit |
c600df |
imageToTiff (ImageCMYK16 img) = encodeTiff img
|
|
Packit |
c600df |
imageToTiff (ImageRGB8 img) = encodeTiff img
|
|
Packit |
c600df |
imageToTiff (ImageRGBF img) = encodeTiff $ toStandardDef img
|
|
Packit |
c600df |
imageToTiff (ImageRGBA8 img) = encodeTiff img
|
|
Packit |
c600df |
imageToTiff (ImageY8 img) = encodeTiff img
|
|
Packit |
c600df |
imageToTiff (ImageYF img) = encodeTiff $ greyScaleToStandardDef img
|
|
Packit |
c600df |
imageToTiff (ImageYA8 img) = encodeTiff $ dropAlphaLayer img
|
|
Packit |
c600df |
imageToTiff (ImageY16 img) = encodeTiff img
|
|
Packit |
c600df |
imageToTiff (ImageYA16 img) = encodeTiff $ dropAlphaLayer img
|
|
Packit |
c600df |
imageToTiff (ImageRGB16 img) = encodeTiff img
|
|
Packit |
c600df |
imageToTiff (ImageRGBA16 img) = encodeTiff img
|
|
Packit |
c600df |
|
|
Packit |
c600df |
-- | This function will try to do anything to encode an image
|
|
Packit |
c600df |
-- as bitmap, make all color conversion and such. Equivalent
|
|
Packit |
c600df |
-- of 'decodeImage' for Bitmap encoding
|
|
Packit |
c600df |
imageToBitmap :: DynamicImage -> L.ByteString
|
|
Packit |
c600df |
imageToBitmap (ImageYCbCr8 img) = encodeBitmap (convertImage img :: Image PixelRGB8)
|
|
Packit |
c600df |
imageToBitmap (ImageCMYK8 img) = encodeBitmap (convertImage img :: Image PixelRGB8)
|
|
Packit |
c600df |
imageToBitmap (ImageCMYK16 img) = imageToBitmap . ImageRGB16 $ convertImage img
|
|
Packit |
c600df |
imageToBitmap (ImageRGBF img) = encodeBitmap $ toStandardDef img
|
|
Packit |
c600df |
imageToBitmap (ImageRGB8 img) = encodeBitmap img
|
|
Packit |
c600df |
imageToBitmap (ImageRGBA8 img) = encodeBitmap img
|
|
Packit |
c600df |
imageToBitmap (ImageY8 img) = encodeBitmap img
|
|
Packit |
c600df |
imageToBitmap (ImageYF img) = encodeBitmap $ greyScaleToStandardDef img
|
|
Packit |
c600df |
imageToBitmap (ImageYA8 img) = encodeBitmap (promoteImage img :: Image PixelRGBA8)
|
|
Packit |
c600df |
imageToBitmap (ImageY16 img) = imageToBitmap . ImageY8 $ from16to8 img
|
|
Packit |
c600df |
imageToBitmap (ImageYA16 img) = imageToBitmap . ImageYA8 $ from16to8 img
|
|
Packit |
c600df |
imageToBitmap (ImageRGB16 img) = imageToBitmap . ImageRGB8 $ from16to8 img
|
|
Packit |
c600df |
imageToBitmap (ImageRGBA16 img) = imageToBitmap . ImageRGBA8 $ from16to8 img
|
|
Packit |
c600df |
|
|
Packit |
c600df |
|
|
Packit |
c600df |
-- | This function will try to do anything to encode an image
|
|
Packit |
c600df |
-- as a gif, make all color conversion and quantization. Equivalent
|
|
Packit |
c600df |
-- of 'decodeImage' for gif encoding
|
|
Packit |
c600df |
imageToGif :: DynamicImage -> Either String L.ByteString
|
|
Packit |
c600df |
imageToGif (ImageYCbCr8 img) = imageToGif . ImageRGB8 $ convertImage img
|
|
Packit |
c600df |
imageToGif (ImageCMYK8 img) = imageToGif . ImageRGB8 $ convertImage img
|
|
Packit |
c600df |
imageToGif (ImageCMYK16 img) = imageToGif . ImageRGB16 $ convertImage img
|
|
Packit |
c600df |
imageToGif (ImageRGBF img) = imageToGif . ImageRGB8 $ toStandardDef img
|
|
Packit |
c600df |
imageToGif (ImageRGB8 img) = encodeGifImageWithPalette indexed pal
|
|
Packit |
c600df |
where (indexed, pal) = palettize defaultPaletteOptions img
|
|
Packit |
c600df |
imageToGif (ImageRGBA8 img) = imageToGif . ImageRGB8 $ dropAlphaLayer img
|
|
Packit |
c600df |
imageToGif (ImageY8 img) = Right $ encodeGifImage img
|
|
Packit |
c600df |
imageToGif (ImageYF img) = imageToGif . ImageY8 $ greyScaleToStandardDef img
|
|
Packit |
c600df |
imageToGif (ImageYA8 img) = imageToGif . ImageY8 $ dropAlphaLayer img
|
|
Packit |
c600df |
imageToGif (ImageY16 img) = imageToGif . ImageY8 $ from16to8 img
|
|
Packit |
c600df |
imageToGif (ImageYA16 img) = imageToGif . ImageYA8 $ from16to8 img
|
|
Packit |
c600df |
imageToGif (ImageRGB16 img) = imageToGif . ImageRGB8 $ from16to8 img
|
|
Packit |
c600df |
imageToGif (ImageRGBA16 img) = imageToGif . ImageRGBA8 $ from16to8 img
|
|
Packit |
c600df |
|
|
Packit |
c600df |
-- | This function will try to do anything to encode an image
|
|
Packit |
c600df |
-- as a tga, make all color conversion and quantization. Equivalent
|
|
Packit |
c600df |
-- of 'decodeImage' for tga encoding
|
|
Packit |
c600df |
imageToTga :: DynamicImage -> L.ByteString
|
|
Packit |
c600df |
imageToTga (ImageYCbCr8 img) = encodeTga (convertImage img :: Image PixelRGB8)
|
|
Packit |
c600df |
imageToTga (ImageCMYK8 img) = encodeTga (convertImage img :: Image PixelRGB8)
|
|
Packit |
c600df |
imageToTga (ImageCMYK16 img) = encodeTga (from16to8 img :: Image PixelRGB8)
|
|
Packit |
c600df |
imageToTga (ImageRGBF img) = encodeTga $ toStandardDef img
|
|
Packit |
c600df |
imageToTga (ImageRGB8 img) = encodeTga img
|
|
Packit |
c600df |
imageToTga (ImageRGBA8 img) = encodeTga img
|
|
Packit |
c600df |
imageToTga (ImageY8 img) = encodeTga img
|
|
Packit |
c600df |
imageToTga (ImageYF img) = encodeTga $ greyScaleToStandardDef img
|
|
Packit |
c600df |
imageToTga (ImageYA8 img) = encodeTga (promoteImage img :: Image PixelRGBA8)
|
|
Packit |
c600df |
imageToTga (ImageY16 img) = encodeTga (from16to8 img :: Image Pixel8)
|
|
Packit |
c600df |
imageToTga (ImageYA16 img) = encodeTga (from16to8 img :: Image PixelRGBA8)
|
|
Packit |
c600df |
imageToTga (ImageRGB16 img) = encodeTga (from16to8 img :: Image PixelRGB8)
|
|
Packit |
c600df |
imageToTga (ImageRGBA16 img) = encodeTga (from16to8 img :: Image PixelRGBA8)
|