{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ScopedTypeVariables #-}
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 )
class PngPaletteSaveable a where
encodePalettedPng :: Image a -> Image Pixel8 -> Either String Lb.ByteString
encodePalettedPng = Metadatas -> Image a -> Image Pixel8 -> Either String ByteString
forall a.
PngPaletteSaveable a =>
Metadatas -> Image a -> Image Pixel8 -> Either String ByteString
encodePalettedPngWithMetadata Metadatas
forall a. Monoid a => a
mempty
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 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 Bool -> Bool -> Bool
|| Int
w Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
256 Bool -> Bool -> Bool
|| Int
h Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
1 = String -> Either String ByteString
forall a b. a -> Either a b
Left String
"Invalid palette"
| (Pixel8 -> Bool) -> Vector Pixel8 -> Bool
forall a. Storable a => (a -> Bool) -> Vector a -> Bool
VS.any Pixel8 -> Bool
isTooBig (Vector Pixel8 -> Bool) -> Vector Pixel8 -> Bool
forall a b. (a -> b) -> a -> b
$ Image Pixel8 -> Vector (PixelBaseComponent Pixel8)
forall a. Image a -> Vector (PixelBaseComponent a)
imageData Image Pixel8
img =
String -> Either String ByteString
forall a b. a -> Either a b
Left String
"Image contains indexes absent from the palette"
| Bool
otherwise = ByteString -> Either String ByteString
forall a b. b -> Either a b
Right (ByteString -> Either String ByteString)
-> ByteString -> Either String ByteString
forall a b. (a -> b) -> a -> b
$ Maybe (Image PixelRGB8)
-> Maybe (Vector Pixel8)
-> PngImageType
-> Metadatas
-> Image Pixel8
-> ByteString
forall px.
(Pixel px, PixelBaseComponent px ~ Pixel8) =>
Maybe (Image PixelRGB8)
-> Maybe (Vector Pixel8)
-> PngImageType
-> Metadatas
-> Image px
-> ByteString
genericEncodePng (Image PixelRGB8 -> Maybe (Image PixelRGB8)
forall a. a -> Maybe a
Just Image PixelRGB8
pal) Maybe (Vector Pixel8)
forall a. Maybe a
Nothing PngImageType
PngIndexedColor Metadatas
metas Image Pixel8
img
where w :: Int
w = Image PixelRGB8 -> Int
forall a. Image a -> Int
imageWidth Image PixelRGB8
pal
h :: Int
h = Image PixelRGB8 -> Int
forall a. Image a -> Int
imageHeight Image PixelRGB8
pal
isTooBig :: Pixel8 -> Bool
isTooBig Pixel8
v = Pixel8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Pixel8
v Int -> Int -> Bool
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 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 Bool -> Bool -> Bool
|| Int
w Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
256 Bool -> Bool -> Bool
|| Int
h Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
1 = String -> Either String ByteString
forall a b. a -> Either a b
Left String
"Invalid palette"
| (Pixel8 -> Bool) -> Vector Pixel8 -> Bool
forall a. Storable a => (a -> Bool) -> Vector a -> Bool
VS.any Pixel8 -> Bool
isTooBig (Vector Pixel8 -> Bool) -> Vector Pixel8 -> Bool
forall a b. (a -> b) -> a -> b
$ Image Pixel8 -> Vector (PixelBaseComponent Pixel8)
forall a. Image a -> Vector (PixelBaseComponent a)
imageData Image Pixel8
img =
String -> Either String ByteString
forall a b. a -> Either a b
Left String
"Image contains indexes absent from the palette"
| Bool
otherwise = ByteString -> Either String ByteString
forall a b. b -> Either a b
Right (ByteString -> Either String ByteString)
-> ByteString -> Either String ByteString
forall a b. (a -> b) -> a -> b
$ Maybe (Image PixelRGB8)
-> Maybe (Vector Pixel8)
-> PngImageType
-> Metadatas
-> Image Pixel8
-> ByteString
forall px.
(Pixel px, PixelBaseComponent px ~ Pixel8) =>
Maybe (Image PixelRGB8)
-> Maybe (Vector Pixel8)
-> PngImageType
-> Metadatas
-> Image px
-> ByteString
genericEncodePng (Image PixelRGB8 -> Maybe (Image PixelRGB8)
forall a. a -> Maybe a
Just Image PixelRGB8
opaquePalette) (Vector Pixel8 -> Maybe (Vector Pixel8)
forall a. a -> Maybe a
Just Vector Pixel8
Vector (PixelBaseComponent Pixel8)
alphaPal) PngImageType
PngIndexedColor Metadatas
metas Image Pixel8
img
where
w :: Int
w = Image PixelRGBA8 -> Int
forall a. Image a -> Int
imageWidth Image PixelRGBA8
pal
h :: Int
h = Image PixelRGBA8 -> Int
forall a. Image a -> Int
imageHeight Image PixelRGBA8
pal
opaquePalette :: Image PixelRGB8
opaquePalette = Image PixelRGBA8 -> Image PixelRGB8
forall a b. TransparentPixel a b => Image a -> Image b
dropAlphaLayer Image PixelRGBA8
pal
alphaPal :: Vector (PixelBaseComponent Pixel8)
alphaPal = Image Pixel8 -> Vector (PixelBaseComponent Pixel8)
forall a. Image a -> Vector (PixelBaseComponent a)
imageData (Image Pixel8 -> Vector (PixelBaseComponent Pixel8))
-> Image Pixel8 -> Vector (PixelBaseComponent Pixel8)
forall a b. (a -> b) -> a -> b
$ PlaneAlpha
-> Image PixelRGBA8 -> Image (PixelBaseComponent PixelRGBA8)
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 = Pixel8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Pixel8
v Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
w
class PngSavable a where
encodePng :: Image a -> Lb.ByteString
encodePng = Metadatas -> Image a -> ByteString
forall a. PngSavable a => Metadatas -> Image a -> ByteString
encodePngWithMetadata Metadatas
forall a. Monoid a => a
mempty
encodePngWithMetadata :: Metadatas -> Image a -> Lb.ByteString
preparePngHeader :: Image a -> PngImageType -> Word8 -> PngIHdr
(Image { imageWidth :: forall a. Image a -> Int
imageWidth = Int
w, imageHeight :: forall a. Image a -> Int
imageHeight = Int
h }) PngImageType
imgType Pixel8
depth = PngIHdr :: Word32
-> Word32
-> Pixel8
-> PngImageType
-> Pixel8
-> Pixel8
-> PngInterlaceMethod
-> PngIHdr
PngIHdr
{ width :: Word32
width = Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
w
, height :: Word32
height = Int -> Word32
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
}
writePng :: (PngSavable pixel) => FilePath -> Image pixel -> IO ()
writePng :: String -> Image pixel -> IO ()
writePng String
path Image pixel
img = String -> ByteString -> IO ()
Lb.writeFile String
path (ByteString -> IO ()) -> ByteString -> IO ()
forall a b. (a -> b) -> a -> b
$ Image pixel -> ByteString
forall a. PngSavable a => Image a -> ByteString
encodePng Image pixel
img
endChunk :: PngRawChunk
endChunk :: PngRawChunk
endChunk = ByteString -> ByteString -> PngRawChunk
mkRawChunk ByteString
iENDSignature ByteString
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 :: 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 }) =
PngRawImage -> ByteString
forall a. Binary a => a -> ByteString
encode PngRawImage :: PngIHdr -> [PngRawChunk] -> PngRawImage
PngRawImage { header :: PngIHdr
header = PngIHdr
hdr
, chunks :: [PngRawChunk]
chunks = Metadatas -> [PngRawChunk]
encodeMetadatas Metadatas
metas
[PngRawChunk] -> [PngRawChunk] -> [PngRawChunk]
forall a. Semigroup a => a -> a -> a
<> [ ByteString -> PngRawChunk
prepareIDatChunk ByteString
imgEncodedData
, PngRawChunk
endChunk
]
}
where hdr :: PngIHdr
hdr = Image px -> PngImageType -> Pixel8 -> PngIHdr
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 = px -> Int
forall a. Pixel a => a -> Int
componentCount (px
forall a. HasCallStack => a
undefined :: px)
lineSize :: Int
lineSize = Int
compCount Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
w
blitToByteString :: Vector Pixel8 -> ByteString
blitToByteString Vector Pixel8
vec = Vector Pixel8 -> Int -> Int -> ByteString
blitVector Vector Pixel8
vec Int
0 (Int
lineSize Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
2)
encodeLine :: Int -> ByteString
encodeLine Int
line = Vector Pixel8 -> ByteString
blitToByteString (Vector Pixel8 -> ByteString) -> Vector Pixel8 -> ByteString
forall a b. (a -> b) -> a -> b
$ (forall s. ST s (Vector Pixel8)) -> Vector Pixel8
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s (Vector Pixel8)) -> Vector Pixel8)
-> (forall s. ST s (Vector Pixel8)) -> Vector Pixel8
forall a b. (a -> b) -> a -> b
$ do
STVector s Pixel8
finalVec <- Int -> ST s (MVector (PrimState (ST s)) Pixel8)
forall (m :: * -> *) a.
(PrimMonad m, Storable a) =>
Int -> m (MVector (PrimState m) a)
M.new (Int -> ST s (MVector (PrimState (ST s)) Pixel8))
-> Int -> ST s (MVector (PrimState (ST s)) Pixel8)
forall a b. (a -> b) -> a -> b
$ Int
lineSize Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
2 :: ST s (M.STVector s Word8)
let baseIndex :: Int
baseIndex = Int
line Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
lineSize
[Int] -> (Int -> ST s ()) -> ST s ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [Int
0 .. Int
lineSize Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1] ((Int -> ST s ()) -> ST s ()) -> (Int -> ST s ()) -> ST s ()
forall a b. (a -> b) -> a -> b
$ \Int
ix -> do
let v :: Word16
v = Vector Word16
Vector (PixelBaseComponent px)
arr Vector Word16 -> Int -> Word16
forall a. Storable a => Vector a -> Int -> a
`VS.unsafeIndex` (Int
baseIndex Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
ix)
high :: Pixel8
high = Word16 -> Pixel8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word16 -> Pixel8) -> Word16 -> Pixel8
forall a b. (a -> b) -> a -> b
$ (Word16
v Word16 -> Int -> Word16
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
8) Word16 -> Word16 -> Word16
forall a. Bits a => a -> a -> a
.&. Word16
0xFF
low :: Pixel8
low = Word16 -> Pixel8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word16 -> Pixel8) -> Word16 -> Pixel8
forall a b. (a -> b) -> a -> b
$ Word16
v Word16 -> Word16 -> Word16
forall a. Bits a => a -> a -> a
.&. Word16
0xFF
(STVector s Pixel8
MVector (PrimState (ST s)) Pixel8
finalVec MVector (PrimState (ST s)) Pixel8 -> Int -> Pixel8 -> ST s ()
forall (m :: * -> *) a.
(PrimMonad m, Storable a) =>
MVector (PrimState m) a -> Int -> a -> m ()
`M.unsafeWrite` (Int
ix Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
0)) Pixel8
high
(STVector s Pixel8
MVector (PrimState (ST s)) Pixel8
finalVec MVector (PrimState (ST s)) Pixel8 -> Int -> Pixel8 -> ST s ()
forall (m :: * -> *) a.
(PrimMonad m, Storable a) =>
MVector (PrimState m) a -> Int -> a -> m ()
`M.unsafeWrite` (Int
ix Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)) Pixel8
low
MVector (PrimState (ST s)) Pixel8 -> ST s (Vector Pixel8)
forall a (m :: * -> *).
(Storable a, PrimMonad m) =>
MVector (PrimState m) a -> m (Vector a)
VS.unsafeFreeze STVector s Pixel8
MVector (PrimState (ST s)) Pixel8
finalVec
imgEncodedData :: ByteString
imgEncodedData = ByteString -> ByteString
Z.compress (ByteString -> ByteString)
-> ([ByteString] -> ByteString) -> [ByteString] -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ByteString] -> ByteString
Lb.fromChunks
([ByteString] -> ByteString) -> [ByteString] -> ByteString
forall a b. (a -> b) -> a -> b
$ [[ByteString]] -> [ByteString]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[ByteString
zero, Int -> ByteString
encodeLine Int
line] | Int
line <- [Int
0 .. Int
h Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1]]
preparePalette :: Palette -> PngRawChunk
preparePalette :: Image PixelRGB8 -> PngRawChunk
preparePalette Image PixelRGB8
pal = PngRawChunk :: Word32 -> ByteString -> Word32 -> ByteString -> PngRawChunk
PngRawChunk
{ chunkLength :: Word32
chunkLength = Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word32) -> Int -> Word32
forall a b. (a -> b) -> a -> b
$ Image PixelRGB8 -> Int
forall a. Image a -> Int
imageWidth Image PixelRGB8
pal Int -> Int -> Int
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 [Vector Pixel8 -> ByteString
forall a. Storable a => Vector a -> ByteString
toByteString (Vector Pixel8 -> ByteString) -> Vector Pixel8 -> ByteString
forall a b. (a -> b) -> a -> b
$ Image PixelRGB8 -> Vector (PixelBaseComponent PixelRGB8)
forall a. Image a -> Vector (PixelBaseComponent a)
imageData Image PixelRGB8
pal]
preparePaletteAlpha :: VS.Vector Pixel8 -> PngRawChunk
preparePaletteAlpha :: Vector Pixel8 -> PngRawChunk
preparePaletteAlpha Vector Pixel8
alphaPal = PngRawChunk :: Word32 -> ByteString -> Word32 -> ByteString -> PngRawChunk
PngRawChunk
{ chunkLength :: Word32
chunkLength = Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word32) -> Int -> Word32
forall a b. (a -> b) -> a -> b
$ Vector Pixel8 -> Int
forall a. Storable a => Vector a -> Int
VS.length Vector Pixel8
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 [Vector Pixel8 -> ByteString
forall a. Storable a => Vector a -> ByteString
toByteString Vector Pixel8
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 :: Maybe (Image PixelRGB8)
-> Maybe (Vector Pixel8)
-> PngImageType
-> Metadatas
-> Image px
-> ByteString
genericEncodePng Maybe (Image PixelRGB8)
palette Maybe (Vector Pixel8)
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 }) =
PngRawImage -> ByteString
forall a. Binary a => a -> ByteString
encode PngRawImage :: PngIHdr -> [PngRawChunk] -> PngRawImage
PngRawImage { header :: PngIHdr
header = PngIHdr
hdr
, chunks :: [PngRawChunk]
chunks = Metadatas -> [PngRawChunk]
encodeMetadatas Metadatas
metas
[PngRawChunk] -> [PngRawChunk] -> [PngRawChunk]
forall a. Semigroup a => a -> a -> a
<> [PngRawChunk]
paletteChunk
[PngRawChunk] -> [PngRawChunk] -> [PngRawChunk]
forall a. Semigroup a => a -> a -> a
<> [PngRawChunk]
transpChunk
[PngRawChunk] -> [PngRawChunk] -> [PngRawChunk]
forall a. Semigroup a => a -> a -> a
<> [ ByteString -> PngRawChunk
prepareIDatChunk ByteString
imgEncodedData
, PngRawChunk
endChunk
]}
where
hdr :: PngIHdr
hdr = Image px -> PngImageType -> Pixel8 -> PngIHdr
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 = px -> Int
forall a. Pixel a => a -> Int
componentCount (px
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 (Vector Pixel8)
palAlpha of
Maybe (Vector Pixel8)
Nothing -> []
Just Vector Pixel8
p -> [Vector Pixel8 -> PngRawChunk
preparePaletteAlpha Vector Pixel8
p]
lineSize :: Int
lineSize = Int
compCount Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
w
encodeLine :: Int -> ByteString
encodeLine Int
line = Vector Pixel8 -> Int -> Int -> ByteString
blitVector Vector Pixel8
Vector (PixelBaseComponent px)
arr (Int
line Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
lineSize) Int
lineSize
imgEncodedData :: ByteString
imgEncodedData = ByteString -> ByteString
Z.compress
(ByteString -> ByteString)
-> ([ByteString] -> ByteString) -> [ByteString] -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ByteString] -> ByteString
Lb.fromChunks
([ByteString] -> ByteString) -> [ByteString] -> ByteString
forall a b. (a -> b) -> a -> b
$ [[ByteString]] -> [ByteString]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[ByteString
zero, Int -> ByteString
encodeLine Int
line] | Int
line <- [Int
0 .. Int
h Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1]]
instance PngSavable PixelRGBA8 where
encodePngWithMetadata :: Metadatas -> Image PixelRGBA8 -> ByteString
encodePngWithMetadata = Maybe (Image PixelRGB8)
-> Maybe (Vector Pixel8)
-> PngImageType
-> Metadatas
-> Image PixelRGBA8
-> ByteString
forall px.
(Pixel px, PixelBaseComponent px ~ Pixel8) =>
Maybe (Image PixelRGB8)
-> Maybe (Vector Pixel8)
-> PngImageType
-> Metadatas
-> Image px
-> ByteString
genericEncodePng Maybe (Image PixelRGB8)
forall a. Maybe a
Nothing Maybe (Vector Pixel8)
forall a. Maybe a
Nothing PngImageType
PngTrueColourWithAlpha
instance PngSavable PixelRGB8 where
encodePngWithMetadata :: Metadatas -> Image PixelRGB8 -> ByteString
encodePngWithMetadata = Maybe (Image PixelRGB8)
-> Maybe (Vector Pixel8)
-> PngImageType
-> Metadatas
-> Image PixelRGB8
-> ByteString
forall px.
(Pixel px, PixelBaseComponent px ~ Pixel8) =>
Maybe (Image PixelRGB8)
-> Maybe (Vector Pixel8)
-> PngImageType
-> Metadatas
-> Image px
-> ByteString
genericEncodePng Maybe (Image PixelRGB8)
forall a. Maybe a
Nothing Maybe (Vector Pixel8)
forall a. Maybe a
Nothing PngImageType
PngTrueColour
instance PngSavable Pixel8 where
encodePngWithMetadata :: Metadatas -> Image Pixel8 -> ByteString
encodePngWithMetadata = Maybe (Image PixelRGB8)
-> Maybe (Vector Pixel8)
-> PngImageType
-> Metadatas
-> Image Pixel8
-> ByteString
forall px.
(Pixel px, PixelBaseComponent px ~ Pixel8) =>
Maybe (Image PixelRGB8)
-> Maybe (Vector Pixel8)
-> PngImageType
-> Metadatas
-> Image px
-> ByteString
genericEncodePng Maybe (Image PixelRGB8)
forall a. Maybe a
Nothing Maybe (Vector Pixel8)
forall a. Maybe a
Nothing PngImageType
PngGreyscale
instance PngSavable PixelYA8 where
encodePngWithMetadata :: Metadatas -> Image PixelYA8 -> ByteString
encodePngWithMetadata = Maybe (Image PixelRGB8)
-> Maybe (Vector Pixel8)
-> PngImageType
-> Metadatas
-> Image PixelYA8
-> ByteString
forall px.
(Pixel px, PixelBaseComponent px ~ Pixel8) =>
Maybe (Image PixelRGB8)
-> Maybe (Vector Pixel8)
-> PngImageType
-> Metadatas
-> Image px
-> ByteString
genericEncodePng Maybe (Image PixelRGB8)
forall a. Maybe a
Nothing Maybe (Vector Pixel8)
forall a. Maybe a
Nothing PngImageType
PngGreyscaleWithAlpha
instance PngSavable PixelYA16 where
encodePngWithMetadata :: Metadatas -> Image PixelYA16 -> ByteString
encodePngWithMetadata = PngImageType -> Metadatas -> Image PixelYA16 -> ByteString
forall px.
(Pixel px, PixelBaseComponent px ~ Word16) =>
PngImageType -> Metadatas -> Image px -> ByteString
genericEncode16BitsPng PngImageType
PngGreyscaleWithAlpha
instance PngSavable Pixel16 where
encodePngWithMetadata :: Metadatas -> Image Word16 -> ByteString
encodePngWithMetadata = PngImageType -> Metadatas -> Image Word16 -> ByteString
forall px.
(Pixel px, PixelBaseComponent px ~ Word16) =>
PngImageType -> Metadatas -> Image px -> ByteString
genericEncode16BitsPng PngImageType
PngGreyscale
instance PngSavable PixelRGB16 where
encodePngWithMetadata :: Metadatas -> Image PixelRGB16 -> ByteString
encodePngWithMetadata = PngImageType -> Metadatas -> Image PixelRGB16 -> ByteString
forall px.
(Pixel px, PixelBaseComponent px ~ Word16) =>
PngImageType -> Metadatas -> Image px -> ByteString
genericEncode16BitsPng PngImageType
PngTrueColour
instance PngSavable PixelRGBA16 where
encodePngWithMetadata :: Metadatas -> Image PixelRGBA16 -> ByteString
encodePngWithMetadata = PngImageType -> Metadatas -> Image PixelRGBA16 -> ByteString
forall px.
(Pixel px, PixelBaseComponent px ~ Word16) =>
PngImageType -> Metadatas -> Image px -> ByteString
genericEncode16BitsPng PngImageType
PngTrueColourWithAlpha
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 -> Either String Bool -> IO (Either String Bool)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String Bool -> IO (Either String Bool))
-> Either String Bool -> IO (Either String Bool)
forall a b. (a -> b) -> a -> b
$ String -> Either String Bool
forall a b. a -> Either a b
Left String
err
Right ByteString
b -> String -> ByteString -> IO ()
Lb.writeFile String
path ByteString
b IO () -> IO (Either String Bool) -> IO (Either String Bool)
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Either String Bool -> IO (Either String Bool)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> Either String Bool
forall a b. b -> Either a b
Right Bool
True)
encodeDynamicPng :: DynamicImage -> Either String Lb.ByteString
encodeDynamicPng :: DynamicImage -> Either String ByteString
encodeDynamicPng (ImageRGB8 Image PixelRGB8
img) = ByteString -> Either String ByteString
forall a b. b -> Either a b
Right (ByteString -> Either String ByteString)
-> ByteString -> Either String ByteString
forall a b. (a -> b) -> a -> b
$ Image PixelRGB8 -> ByteString
forall a. PngSavable a => Image a -> ByteString
encodePng Image PixelRGB8
img
encodeDynamicPng (ImageRGBA8 Image PixelRGBA8
img) = ByteString -> Either String ByteString
forall a b. b -> Either a b
Right (ByteString -> Either String ByteString)
-> ByteString -> Either String ByteString
forall a b. (a -> b) -> a -> b
$ Image PixelRGBA8 -> ByteString
forall a. PngSavable a => Image a -> ByteString
encodePng Image PixelRGBA8
img
encodeDynamicPng (ImageY8 Image Pixel8
img) = ByteString -> Either String ByteString
forall a b. b -> Either a b
Right (ByteString -> Either String ByteString)
-> ByteString -> Either String ByteString
forall a b. (a -> b) -> a -> b
$ Image Pixel8 -> ByteString
forall a. PngSavable a => Image a -> ByteString
encodePng Image Pixel8
img
encodeDynamicPng (ImageY16 Image Word16
img) = ByteString -> Either String ByteString
forall a b. b -> Either a b
Right (ByteString -> Either String ByteString)
-> ByteString -> Either String ByteString
forall a b. (a -> b) -> a -> b
$ Image Word16 -> ByteString
forall a. PngSavable a => Image a -> ByteString
encodePng Image Word16
img
encodeDynamicPng (ImageYA8 Image PixelYA8
img) = ByteString -> Either String ByteString
forall a b. b -> Either a b
Right (ByteString -> Either String ByteString)
-> ByteString -> Either String ByteString
forall a b. (a -> b) -> a -> b
$ Image PixelYA8 -> ByteString
forall a. PngSavable a => Image a -> ByteString
encodePng Image PixelYA8
img
encodeDynamicPng (ImageYA16 Image PixelYA16
img) = ByteString -> Either String ByteString
forall a b. b -> Either a b
Right (ByteString -> Either String ByteString)
-> ByteString -> Either String ByteString
forall a b. (a -> b) -> a -> b
$ Image PixelYA16 -> ByteString
forall a. PngSavable a => Image a -> ByteString
encodePng Image PixelYA16
img
encodeDynamicPng (ImageRGB16 Image PixelRGB16
img) = ByteString -> Either String ByteString
forall a b. b -> Either a b
Right (ByteString -> Either String ByteString)
-> ByteString -> Either String ByteString
forall a b. (a -> b) -> a -> b
$ Image PixelRGB16 -> ByteString
forall a. PngSavable a => Image a -> ByteString
encodePng Image PixelRGB16
img
encodeDynamicPng (ImageRGBA16 Image PixelRGBA16
img) = ByteString -> Either String ByteString
forall a b. b -> Either a b
Right (ByteString -> Either String ByteString)
-> ByteString -> Either String ByteString
forall a b. (a -> b) -> a -> b
$ Image PixelRGBA16 -> ByteString
forall a. PngSavable a => Image a -> ByteString
encodePng Image PixelRGBA16
img
encodeDynamicPng DynamicImage
_ = String -> Either String ByteString
forall a b. a -> Either a b
Left String
"Unsupported image format for PNG export"