module File.Binary.PNG.DataChunks ( module File.Binary.PNG.Chunks, makePNGHeader, bsToPNGImage, pngImageToBS, PNGImageL(..), PNGImageLColor(..), readIccp ) where import File.Binary.PNG.Data import File.Binary.PNG.Chunks import Data.Bits import qualified Data.ByteString.Lazy as BSL import Data.List bsToPNGImage :: PNGImage pi => IHDR -> Maybe PLTE -> Maybe TRNS -> BSL.ByteString -> Either String pi bsToPNGImage ihdr plte trns bs = do h <- makePNGHeader ihdr plte trns return $ makePNGImage h bs pngImageToBS :: PNGImage pi => pi -> (IHDR, Maybe TRNS, BSL.ByteString) pngImageToBS pi = let (header, bs) = fromPNGImage pi (ihdr, trns) = fromPNGHeader header in (ihdr, trns, bs) makePNGHeader :: IHDR -> Maybe PLTE -> Maybe TRNS -> Either String PNGHeader makePNGHeader ihdr plte trns = do ct <- getColorType (alpha ihdr) (color ihdr) (palet ihdr) trns return PNGHeader { pngWidth = width ihdr, pngHeight = height ihdr, pngDepth = depth ihdr, pngColorType = ct, pngCompType = compressionType ihdr, pngFilterType = filterType ihdr, pngInterlaceType = interlaceType ihdr, pngPalette = maybe [] plteToInts plte } plteToInts :: PLTE -> [(Int, Int, Int)] plteToInts = map (\(RGB8 r g b) -> (fi r, fi g, fi b)) . colors where fi = fromIntegral fromPNGHeader :: PNGHeader -> (IHDR, Maybe TRNS) fromPNGHeader ph@PNGHeader { pngColorType = PNGTypeColor Nothing } = (IHDR { width = pngWidth ph, height = pngHeight ph, depth = pngDepth ph, alpha = False, color = True, palet = False, compressionType = 0, filterType = 0, interlaceType = 0 }, Nothing) getTRNSChunk :: [Chunk] -> Maybe Chunk getTRNSChunk = find ((== T_tRNS) . typeChunk) getColorType :: Bool -> Bool -> Bool -> Maybe TRNS -> Either String PNGColorType getColorType False True True = return . PNGTypeIndex . maybe [] readTRNSi getColorType False False False = return . PNGTypeGrey . fmap readTRNSg getColorType False True False = return . PNGTypeColor . fmap readTRNSc getColorType True False False = const $ return PNGTypeGreyAlpha getColorType True True False = const $ return PNGTypeColorAlpha getColorType _ _ _ = fail "bad colortype" readTRNSi :: TRNS -> [Int] readTRNSi = map fromIntegral . BSL.unpack . dat readTRNSg :: TRNS -> Int readTRNSg t = let [h, l] = map fromIntegral $ BSL.unpack $ dat t in h `shiftL` 8 .|. l readTRNSc :: TRNS -> (Int, Int, Int) readTRNSc t = let [rh, rl, gh, gl, bh, bl] = map fromIntegral $ BSL.unpack $ dat t in ( rh `shiftL` 8 .|. rl, gh `shiftL` 8 .|. gl, bh `shiftL` 8 .|. bl)