{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ScopedTypeVariables #-}
-- | Module implementing a basic png export, no filtering is applyed, but

-- export at least valid images.

module Codec.Picture.Png.Internal.Export( PngSavable( .. )
                               , PngPaletteSaveable( .. )
                               , writePng
                               , encodeDynamicPng
                               , writeDynamicPng
                               ) where
#if !MIN_VERSION_base(4,8,0)
import Data.Monoid( mempty )
#endif

import Control.Monad( forM_ )
import Control.Monad.ST( ST, runST )
import Data.Bits( unsafeShiftR, (.&.) )
import Data.Binary( encode )
#if !MIN_VERSION_base(4,11,0)
import Data.Monoid( (<>) )
#endif
import Data.Word(Word8, Word16)
import qualified Codec.Compression.Zlib as Z
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as Lb

import qualified Data.Vector.Storable as VS
import qualified Data.Vector.Storable.Mutable as M

import Codec.Picture.Types
import Codec.Picture.Png.Internal.Type
import Codec.Picture.Png.Internal.Metadata
import Codec.Picture.Metadata( Metadatas )
import Codec.Picture.VectorByteConversion( blitVector, toByteString )

-- | Encode a paletted image into a png if possible.

class PngPaletteSaveable a where
  -- | Encode a paletted image as a color indexed 8-bit PNG.

  -- the palette must have between 1 and 256 values in it.

  -- Accepts `PixelRGB8` and `PixelRGBA8` as palette pixel type

  encodePalettedPng :: Image a -> Image Pixel8 -> Either String Lb.ByteString
  encodePalettedPng = forall a.
PngPaletteSaveable a =>
Metadatas -> Image a -> Image Pixel8 -> Either String ByteString
encodePalettedPngWithMetadata forall a. Monoid a => a
mempty

  -- | Equivalent to 'encodePalettedPng' but allow writing of metadatas.

  -- See `encodePngWithMetadata` for the details of encoded metadatas

  -- Accepts `PixelRGB8` and `PixelRGBA8` as palette pixel type

  encodePalettedPngWithMetadata :: Metadatas -> Image a -> Image Pixel8 -> Either String Lb.ByteString

instance PngPaletteSaveable PixelRGB8 where
  encodePalettedPngWithMetadata :: Metadatas
-> Image PixelRGB8 -> Image Pixel8 -> Either String ByteString
encodePalettedPngWithMetadata Metadatas
metas Image PixelRGB8
pal Image Pixel8
img
      | Int
w forall a. Ord a => a -> a -> Bool
<= Int
0 Bool -> Bool -> Bool
|| Int
w forall a. Ord a => a -> a -> Bool
> Int
256 Bool -> Bool -> Bool
|| Int
h forall a. Eq a => a -> a -> Bool
/= Int
1 = forall a b. a -> Either a b
Left String
"Invalid palette"
      | forall a. Storable a => (a -> Bool) -> Vector a -> Bool
VS.any Pixel8 -> Bool
isTooBig forall a b. (a -> b) -> a -> b
$ forall a. Image a -> Vector (PixelBaseComponent a)
imageData Image Pixel8
img =
          forall a b. a -> Either a b
Left String
"Image contains indexes absent from the palette"
      | Bool
otherwise = forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ forall px.
(Pixel px, PixelBaseComponent px ~ Pixel8) =>
Maybe (Image PixelRGB8)
-> Maybe PaletteAlpha
-> PngImageType
-> Metadatas
-> Image px
-> ByteString
genericEncodePng (forall a. a -> Maybe a
Just Image PixelRGB8
pal) forall a. Maybe a
Nothing PngImageType
PngIndexedColor Metadatas
metas Image Pixel8
img
        where w :: Int
w = forall a. Image a -> Int
imageWidth Image PixelRGB8
pal
              h :: Int
h = forall a. Image a -> Int
imageHeight Image PixelRGB8
pal
              isTooBig :: Pixel8 -> Bool
isTooBig Pixel8
v = forall a b. (Integral a, Num b) => a -> b
fromIntegral Pixel8
v forall a. Ord a => a -> a -> Bool
>= Int
w

instance PngPaletteSaveable PixelRGBA8 where
  encodePalettedPngWithMetadata :: Metadatas
-> Image PixelRGBA8 -> Image Pixel8 -> Either String ByteString
encodePalettedPngWithMetadata Metadatas
metas Image PixelRGBA8
pal Image Pixel8
img
      | Int
w forall a. Ord a => a -> a -> Bool
<= Int
0 Bool -> Bool -> Bool
|| Int
w forall a. Ord a => a -> a -> Bool
> Int
256 Bool -> Bool -> Bool
|| Int
h forall a. Eq a => a -> a -> Bool
/= Int
1 = forall a b. a -> Either a b
Left String
"Invalid palette"
      | forall a. Storable a => (a -> Bool) -> Vector a -> Bool
VS.any Pixel8 -> Bool
isTooBig forall a b. (a -> b) -> a -> b
$ forall a. Image a -> Vector (PixelBaseComponent a)
imageData Image Pixel8
img =
          forall a b. a -> Either a b
Left String
"Image contains indexes absent from the palette"
      | Bool
otherwise = forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ forall px.
(Pixel px, PixelBaseComponent px ~ Pixel8) =>
Maybe (Image PixelRGB8)
-> Maybe PaletteAlpha
-> PngImageType
-> Metadatas
-> Image px
-> ByteString
genericEncodePng (forall a. a -> Maybe a
Just Image PixelRGB8
opaquePalette) (forall a. a -> Maybe a
Just Vector (PixelBaseComponent Pixel8)
alphaPal) PngImageType
PngIndexedColor Metadatas
metas Image Pixel8
img
    where
      w :: Int
w = forall a. Image a -> Int
imageWidth Image PixelRGBA8
pal
      h :: Int
h = forall a. Image a -> Int
imageHeight Image PixelRGBA8
pal
      opaquePalette :: Image PixelRGB8
opaquePalette = forall a b. TransparentPixel a b => Image a -> Image b
dropAlphaLayer Image PixelRGBA8
pal
      alphaPal :: Vector (PixelBaseComponent Pixel8)
alphaPal = forall a. Image a -> Vector (PixelBaseComponent a)
imageData forall a b. (a -> b) -> a -> b
$ forall px plane.
(Pixel px, Pixel (PixelBaseComponent px),
 PixelBaseComponent (PixelBaseComponent px) ~ PixelBaseComponent px,
 ColorPlane px plane) =>
plane -> Image px -> Image (PixelBaseComponent px)
extractComponent PlaneAlpha
PlaneAlpha Image PixelRGBA8
pal
      isTooBig :: Pixel8 -> Bool
isTooBig Pixel8
v = forall a b. (Integral a, Num b) => a -> b
fromIntegral Pixel8
v forall a. Ord a => a -> a -> Bool
>= Int
w

-- | Encode an image into a png if possible.

class PngSavable a where
    -- | Transform an image into a png encoded bytestring, ready

    -- to be written as a file.

    encodePng :: Image a -> Lb.ByteString
    encodePng = forall a. PngSavable a => Metadatas -> Image a -> ByteString
encodePngWithMetadata forall a. Monoid a => a
mempty

    -- | Encode a png using some metadatas. The following metadata keys will

    -- be stored in a `tEXt` field :

    --

    --  * 'Codec.Picture.Metadata.Title'

    --  * 'Codec.Picture.Metadata.Description'

    --  * 'Codec.Picture.Metadata.Author'

    --  * 'Codec.Picture.Metadata.Copyright'

    --  * 'Codec.Picture.Metadata.Software'

    --  * 'Codec.Picture.Metadata.Comment'

    --  * 'Codec.Picture.Metadata.Disclaimer'

    --  * 'Codec.Picture.Metadata.Source'

    --  * 'Codec.Picture.Metadata.Warning'

    --  * 'Codec.Picture.Metadata.Unknown' using the key present in the constructor.

    -- 

    -- the followings metadata will bes tored in the `gAMA` chunk.

    --

    --  * 'Codec.Picture.Metadata.Gamma'

    --

    -- The followings metadata will be stored in a `pHYs` chunk

    --

    --  * 'Codec.Picture.Metadata.DpiX'

    --  * 'Codec.Picture.Metadata.DpiY' 

    encodePngWithMetadata :: Metadatas -> Image a -> Lb.ByteString

preparePngHeader :: Image a -> PngImageType -> Word8 -> PngIHdr
preparePngHeader :: forall a. Image a -> PngImageType -> Pixel8 -> PngIHdr
preparePngHeader (Image { imageWidth :: forall a. Image a -> Int
imageWidth = Int
w, imageHeight :: forall a. Image a -> Int
imageHeight = Int
h }) PngImageType
imgType Pixel8
depth = PngIHdr
  { width :: Word32
width             = forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
w
  , height :: Word32
height            = forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
h
  , bitDepth :: Pixel8
bitDepth          = Pixel8
depth
  , colourType :: PngImageType
colourType        = PngImageType
imgType
  , compressionMethod :: Pixel8
compressionMethod = Pixel8
0
  , filterMethod :: Pixel8
filterMethod      = Pixel8
0
  , interlaceMethod :: PngInterlaceMethod
interlaceMethod   = PngInterlaceMethod
PngNoInterlace
  }

-- | Helper function to directly write an image as a png on disk.

writePng :: (PngSavable pixel) => FilePath -> Image pixel -> IO ()
writePng :: forall pixel. PngSavable pixel => String -> Image pixel -> IO ()
writePng String
path Image pixel
img = String -> ByteString -> IO ()
Lb.writeFile String
path forall a b. (a -> b) -> a -> b
$ forall a. PngSavable a => Image a -> ByteString
encodePng Image pixel
img

endChunk :: PngRawChunk
endChunk :: PngRawChunk
endChunk = ByteString -> ByteString -> PngRawChunk
mkRawChunk ByteString
iENDSignature forall a. Monoid a => a
mempty

prepareIDatChunk :: Lb.ByteString -> PngRawChunk
prepareIDatChunk :: ByteString -> PngRawChunk
prepareIDatChunk = ByteString -> ByteString -> PngRawChunk
mkRawChunk ByteString
iDATSignature

genericEncode16BitsPng :: forall px. (Pixel px, PixelBaseComponent px ~ Word16)
                       => PngImageType -> Metadatas -> Image px -> Lb.ByteString
genericEncode16BitsPng :: forall px.
(Pixel px, PixelBaseComponent px ~ Pixel16) =>
PngImageType -> Metadatas -> Image px -> ByteString
genericEncode16BitsPng PngImageType
imgKind Metadatas
metas
                 image :: Image px
image@(Image { imageWidth :: forall a. Image a -> Int
imageWidth = Int
w, imageHeight :: forall a. Image a -> Int
imageHeight = Int
h, imageData :: forall a. Image a -> Vector (PixelBaseComponent a)
imageData = Vector (PixelBaseComponent px)
arr }) =
  forall a. Binary a => a -> ByteString
encode PngRawImage { header :: PngIHdr
header = PngIHdr
hdr
                     , chunks :: [PngRawChunk]
chunks = Metadatas -> [PngRawChunk]
encodeMetadatas Metadatas
metas 
                              forall a. Semigroup a => a -> a -> a
<> [ ByteString -> PngRawChunk
prepareIDatChunk ByteString
imgEncodedData
                                 , PngRawChunk
endChunk
                                 ]
                     }
    where hdr :: PngIHdr
hdr = forall a. Image a -> PngImageType -> Pixel8 -> PngIHdr
preparePngHeader Image px
image PngImageType
imgKind Pixel8
16
          zero :: ByteString
zero = Pixel8 -> ByteString
B.singleton Pixel8
0
          compCount :: Int
compCount = forall a. Pixel a => a -> Int
componentCount (forall a. HasCallStack => a
undefined :: px)

          lineSize :: Int
lineSize = Int
compCount forall a. Num a => a -> a -> a
* Int
w
          blitToByteString :: PaletteAlpha -> ByteString
blitToByteString PaletteAlpha
vec = PaletteAlpha -> Int -> Int -> ByteString
blitVector PaletteAlpha
vec Int
0 (Int
lineSize forall a. Num a => a -> a -> a
* Int
2)
          encodeLine :: Int -> ByteString
encodeLine Int
line = PaletteAlpha -> ByteString
blitToByteString forall a b. (a -> b) -> a -> b
$ forall a. (forall s. ST s a) -> a
runST forall a b. (a -> b) -> a -> b
$ do
              STVector s Pixel8
finalVec <- forall (m :: * -> *) a.
(PrimMonad m, Storable a) =>
Int -> m (MVector (PrimState m) a)
M.new forall a b. (a -> b) -> a -> b
$ Int
lineSize forall a. Num a => a -> a -> a
* Int
2 :: ST s (M.STVector s Word8)
              let baseIndex :: Int
baseIndex = Int
line forall a. Num a => a -> a -> a
* Int
lineSize
              forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [Int
0 ..  Int
lineSize forall a. Num a => a -> a -> a
- Int
1] forall a b. (a -> b) -> a -> b
$ \Int
ix -> do
                  let v :: Pixel16
v = Vector (PixelBaseComponent px)
arr forall a. Storable a => Vector a -> Int -> a
`VS.unsafeIndex` (Int
baseIndex forall a. Num a => a -> a -> a
+ Int
ix)
                      high :: Pixel8
high = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ (Pixel16
v forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
8) forall a. Bits a => a -> a -> a
.&. Pixel16
0xFF
                      low :: Pixel8
low = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ Pixel16
v forall a. Bits a => a -> a -> a
.&. Pixel16
0xFF

                  (STVector s Pixel8
finalVec forall (m :: * -> *) a.
(PrimMonad m, Storable a) =>
MVector (PrimState m) a -> Int -> a -> m ()
`M.unsafeWrite` (Int
ix forall a. Num a => a -> a -> a
* Int
2 forall a. Num a => a -> a -> a
+ Int
0)) Pixel8
high
                  (STVector s Pixel8
finalVec forall (m :: * -> *) a.
(PrimMonad m, Storable a) =>
MVector (PrimState m) a -> Int -> a -> m ()
`M.unsafeWrite` (Int
ix forall a. Num a => a -> a -> a
* Int
2 forall a. Num a => a -> a -> a
+ Int
1)) Pixel8
low

              forall a (m :: * -> *).
(Storable a, PrimMonad m) =>
MVector (PrimState m) a -> m (Vector a)
VS.unsafeFreeze STVector s Pixel8
finalVec

          imgEncodedData :: ByteString
imgEncodedData = ByteString -> ByteString
Z.compress forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ByteString] -> ByteString
Lb.fromChunks
                        forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[ByteString
zero, Int -> ByteString
encodeLine Int
line] | Int
line <- [Int
0 .. Int
h forall a. Num a => a -> a -> a
- Int
1]]

preparePalette :: Palette -> PngRawChunk
preparePalette :: Image PixelRGB8 -> PngRawChunk
preparePalette Image PixelRGB8
pal = PngRawChunk
  { chunkLength :: Word32
chunkLength = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall a. Image a -> Int
imageWidth Image PixelRGB8
pal forall a. Num a => a -> a -> a
* Int
3
  , chunkType :: ByteString
chunkType   = ByteString
pLTESignature
  , chunkCRC :: Word32
chunkCRC    = [ByteString] -> Word32
pngComputeCrc [ByteString
pLTESignature, ByteString
binaryData]
  , chunkData :: ByteString
chunkData   = ByteString
binaryData
  }
  where binaryData :: ByteString
binaryData = [ByteString] -> ByteString
Lb.fromChunks [forall a. Storable a => Vector a -> ByteString
toByteString forall a b. (a -> b) -> a -> b
$ forall a. Image a -> Vector (PixelBaseComponent a)
imageData Image PixelRGB8
pal]

preparePaletteAlpha :: VS.Vector Pixel8 -> PngRawChunk
preparePaletteAlpha :: PaletteAlpha -> PngRawChunk
preparePaletteAlpha PaletteAlpha
alphaPal = PngRawChunk
  { chunkLength :: Word32
chunkLength = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall a. Storable a => Vector a -> Int
VS.length PaletteAlpha
alphaPal
  , chunkType :: ByteString
chunkType   = ByteString
tRNSSignature
  , chunkCRC :: Word32
chunkCRC    = [ByteString] -> Word32
pngComputeCrc [ByteString
tRNSSignature, ByteString
binaryData]
  , chunkData :: ByteString
chunkData   = ByteString
binaryData
  }
  where binaryData :: ByteString
binaryData = [ByteString] -> ByteString
Lb.fromChunks [forall a. Storable a => Vector a -> ByteString
toByteString PaletteAlpha
alphaPal]

type PaletteAlpha = VS.Vector Pixel8

genericEncodePng :: forall px. (Pixel px, PixelBaseComponent px ~ Word8)
                 => Maybe Palette
                 -> Maybe PaletteAlpha
                 -> PngImageType -> Metadatas -> Image px
                 -> Lb.ByteString
genericEncodePng :: forall px.
(Pixel px, PixelBaseComponent px ~ Pixel8) =>
Maybe (Image PixelRGB8)
-> Maybe PaletteAlpha
-> PngImageType
-> Metadatas
-> Image px
-> ByteString
genericEncodePng Maybe (Image PixelRGB8)
palette Maybe PaletteAlpha
palAlpha PngImageType
imgKind Metadatas
metas
                 image :: Image px
image@(Image { imageWidth :: forall a. Image a -> Int
imageWidth = Int
w, imageHeight :: forall a. Image a -> Int
imageHeight = Int
h, imageData :: forall a. Image a -> Vector (PixelBaseComponent a)
imageData = Vector (PixelBaseComponent px)
arr }) =
  forall a. Binary a => a -> ByteString
encode PngRawImage { header :: PngIHdr
header = PngIHdr
hdr
                     , chunks :: [PngRawChunk]
chunks = Metadatas -> [PngRawChunk]
encodeMetadatas Metadatas
metas
                              forall a. Semigroup a => a -> a -> a
<> [PngRawChunk]
paletteChunk
                              forall a. Semigroup a => a -> a -> a
<> [PngRawChunk]
transpChunk
                              forall a. Semigroup a => a -> a -> a
<> [ ByteString -> PngRawChunk
prepareIDatChunk ByteString
imgEncodedData
                                 , PngRawChunk
endChunk
                                 ]}
  where
    hdr :: PngIHdr
hdr = forall a. Image a -> PngImageType -> Pixel8 -> PngIHdr
preparePngHeader Image px
image PngImageType
imgKind Pixel8
8
    zero :: ByteString
zero = Pixel8 -> ByteString
B.singleton Pixel8
0
    compCount :: Int
compCount = forall a. Pixel a => a -> Int
componentCount (forall a. HasCallStack => a
undefined :: px)

    paletteChunk :: [PngRawChunk]
paletteChunk = case Maybe (Image PixelRGB8)
palette of
      Maybe (Image PixelRGB8)
Nothing -> []
      Just Image PixelRGB8
p -> [Image PixelRGB8 -> PngRawChunk
preparePalette Image PixelRGB8
p]

    transpChunk :: [PngRawChunk]
transpChunk = case Maybe PaletteAlpha
palAlpha of
      Maybe PaletteAlpha
Nothing -> []
      Just PaletteAlpha
p -> [PaletteAlpha -> PngRawChunk
preparePaletteAlpha PaletteAlpha
p]

    lineSize :: Int
lineSize = Int
compCount forall a. Num a => a -> a -> a
* Int
w
    encodeLine :: Int -> ByteString
encodeLine Int
line = PaletteAlpha -> Int -> Int -> ByteString
blitVector Vector (PixelBaseComponent px)
arr (Int
line forall a. Num a => a -> a -> a
* Int
lineSize) Int
lineSize
    imgEncodedData :: ByteString
imgEncodedData = ByteString -> ByteString
Z.compress
        forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ByteString] -> ByteString
Lb.fromChunks
        forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[ByteString
zero, Int -> ByteString
encodeLine Int
line] | Int
line <- [Int
0 .. Int
h forall a. Num a => a -> a -> a
- Int
1]]

instance PngSavable PixelRGBA8 where
  encodePngWithMetadata :: Metadatas -> Image PixelRGBA8 -> ByteString
encodePngWithMetadata = forall px.
(Pixel px, PixelBaseComponent px ~ Pixel8) =>
Maybe (Image PixelRGB8)
-> Maybe PaletteAlpha
-> PngImageType
-> Metadatas
-> Image px
-> ByteString
genericEncodePng forall a. Maybe a
Nothing forall a. Maybe a
Nothing PngImageType
PngTrueColourWithAlpha

instance PngSavable PixelRGB8 where
  encodePngWithMetadata :: Metadatas -> Image PixelRGB8 -> ByteString
encodePngWithMetadata = forall px.
(Pixel px, PixelBaseComponent px ~ Pixel8) =>
Maybe (Image PixelRGB8)
-> Maybe PaletteAlpha
-> PngImageType
-> Metadatas
-> Image px
-> ByteString
genericEncodePng forall a. Maybe a
Nothing forall a. Maybe a
Nothing PngImageType
PngTrueColour

instance PngSavable Pixel8 where
  encodePngWithMetadata :: Metadatas -> Image Pixel8 -> ByteString
encodePngWithMetadata = forall px.
(Pixel px, PixelBaseComponent px ~ Pixel8) =>
Maybe (Image PixelRGB8)
-> Maybe PaletteAlpha
-> PngImageType
-> Metadatas
-> Image px
-> ByteString
genericEncodePng forall a. Maybe a
Nothing forall a. Maybe a
Nothing PngImageType
PngGreyscale

instance PngSavable PixelYA8 where
  encodePngWithMetadata :: Metadatas -> Image PixelYA8 -> ByteString
encodePngWithMetadata = forall px.
(Pixel px, PixelBaseComponent px ~ Pixel8) =>
Maybe (Image PixelRGB8)
-> Maybe PaletteAlpha
-> PngImageType
-> Metadatas
-> Image px
-> ByteString
genericEncodePng forall a. Maybe a
Nothing forall a. Maybe a
Nothing PngImageType
PngGreyscaleWithAlpha

instance PngSavable PixelYA16 where
  encodePngWithMetadata :: Metadatas -> Image PixelYA16 -> ByteString
encodePngWithMetadata = forall px.
(Pixel px, PixelBaseComponent px ~ Pixel16) =>
PngImageType -> Metadatas -> Image px -> ByteString
genericEncode16BitsPng PngImageType
PngGreyscaleWithAlpha

instance PngSavable Pixel16 where
  encodePngWithMetadata :: Metadatas -> Image Pixel16 -> ByteString
encodePngWithMetadata = forall px.
(Pixel px, PixelBaseComponent px ~ Pixel16) =>
PngImageType -> Metadatas -> Image px -> ByteString
genericEncode16BitsPng PngImageType
PngGreyscale

instance PngSavable PixelRGB16 where
  encodePngWithMetadata :: Metadatas -> Image PixelRGB16 -> ByteString
encodePngWithMetadata = forall px.
(Pixel px, PixelBaseComponent px ~ Pixel16) =>
PngImageType -> Metadatas -> Image px -> ByteString
genericEncode16BitsPng PngImageType
PngTrueColour

instance PngSavable PixelRGBA16 where
  encodePngWithMetadata :: Metadatas -> Image PixelRGBA16 -> ByteString
encodePngWithMetadata = forall px.
(Pixel px, PixelBaseComponent px ~ Pixel16) =>
PngImageType -> Metadatas -> Image px -> ByteString
genericEncode16BitsPng PngImageType
PngTrueColourWithAlpha

-- | Write a dynamic image in a .png image file if possible.

-- The same restriction as encodeDynamicPng apply.

writeDynamicPng :: FilePath -> DynamicImage -> IO (Either String Bool)
writeDynamicPng :: String -> DynamicImage -> IO (Either String Bool)
writeDynamicPng String
path DynamicImage
img = case DynamicImage -> Either String ByteString
encodeDynamicPng DynamicImage
img of
        Left String
err -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b. a -> Either a b
Left String
err
        Right ByteString
b  -> String -> ByteString -> IO ()
Lb.writeFile String
path ByteString
b forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. b -> Either a b
Right Bool
True)

-- | Encode a dynamic image in PNG if possible, supported images are:

--

--   * 'ImageY8'

--

--   * 'ImageY16'

--

--   * 'ImageYA8'

--

--   * 'ImageYA16'

--

--   * 'ImageRGB8'

--

--   * 'ImageRGB16'

--

--   * 'ImageRGBA8'

--

--   * 'ImageRGBA16'

--

encodeDynamicPng :: DynamicImage -> Either String Lb.ByteString
encodeDynamicPng :: DynamicImage -> Either String ByteString
encodeDynamicPng (ImageRGB8 Image PixelRGB8
img) = forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ forall a. PngSavable a => Image a -> ByteString
encodePng Image PixelRGB8
img
encodeDynamicPng (ImageRGBA8 Image PixelRGBA8
img) = forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ forall a. PngSavable a => Image a -> ByteString
encodePng Image PixelRGBA8
img
encodeDynamicPng (ImageY8 Image Pixel8
img) = forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ forall a. PngSavable a => Image a -> ByteString
encodePng Image Pixel8
img
encodeDynamicPng (ImageY16 Image Pixel16
img) = forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ forall a. PngSavable a => Image a -> ByteString
encodePng Image Pixel16
img
encodeDynamicPng (ImageYA8 Image PixelYA8
img) = forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ forall a. PngSavable a => Image a -> ByteString
encodePng Image PixelYA8
img
encodeDynamicPng (ImageYA16 Image PixelYA16
img) = forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ forall a. PngSavable a => Image a -> ByteString
encodePng Image PixelYA16
img
encodeDynamicPng (ImageRGB16 Image PixelRGB16
img) = forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ forall a. PngSavable a => Image a -> ByteString
encodePng Image PixelRGB16
img
encodeDynamicPng (ImageRGBA16 Image PixelRGBA16
img) = forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ forall a. PngSavable a => Image a -> ByteString
encodePng Image PixelRGBA16
img
encodeDynamicPng DynamicImage
_ = forall a b. a -> Either a b
Left String
"Unsupported image format for PNG export"