content: {-# LANGUAGE TupleSections #-}
  
  module Brillo.Juicy (
    -- * Conversion from JuicyPixels' types to brillo' Picture
    fromDynamicImage,
    fromImageRGBA8,
    fromImageRGB8,
    fromImageY8,
    fromImageYA8,
    fromImageYCbCr8,
  
    -- * Loading a brillo Picture from a file through JuicyPixels
    loadJuicy,
    loadJuicyWithMetadata,
    loadJuicyJPG,
    loadJuicyPNG,
  
    -- * From brillo, exported here for convenience
    loadBMP,
  )
  where
  
  import Brillo.Data.Bitmap (
    BitmapFormat (BitmapFormat),
    PixelFormat (PxRGBA),
    RowOrder (TopToBottom),
    bitmapOfForeignPtr,
    loadBMP,
   )
  import Brillo.Data.Picture (Picture)
  import Codec.Picture (
    DynamicImage (
      ImageRGB8,
      ImageRGBA8,
      ImageRGBF,
      ImageY8,
      ImageYA8,
      ImageYCbCr8,
      ImageYF
    ),
    Image (..),
    Pixel8,
    PixelRGB8,
    PixelRGBA8,
    PixelYA8,
    PixelYCbCr8,
    readImage,
    readImageWithMetadata,
    readJpeg,
    readPng,
   )
  import Codec.Picture.Metadata (Metadatas)
  import Codec.Picture.Types (
    ColorConvertible (promoteImage),
    ColorSpaceConvertible (convertImage),
   )
  import Data.Vector.Storable (unsafeToForeignPtr)
  
  
  {-| Tries to convert a 'DynamicImage' from JuicyPixels to a brillo 'Picture'.
  All formats except RGBF and YF should successfully yield a 'Picture'.
  -}
  fromDynamicImage :: DynamicImage -> Maybe Picture
  fromDynamicImage (ImageY8 img) = Just $ fromImageY8 img
  fromDynamicImage (ImageYA8 img) = Just $ fromImageYA8 img
  fromDynamicImage (ImageRGB8 img) = Just $ fromImageRGB8 img
  fromDynamicImage (ImageRGBA8 img) = Just $ fromImageRGBA8 img
  fromDynamicImage (ImageYCbCr8 img) = Just $ fromImageYCbCr8 img
  fromDynamicImage (ImageRGBF _) = Nothing
  fromDynamicImage (ImageYF _) = Nothing
  fromDynamicImage _ = Nothing
  
  
  {-| O(N) conversion from 'PixelRGBA8' image to brillo 'Picture',
  where N is the number of pixels.
  -}
  fromImageRGBA8 :: Image PixelRGBA8 -> Picture
  fromImageRGBA8 (Image{imageWidth = w, imageHeight = h, imageData = imgDat}) = do
    let (ptr, _, _) = unsafeToForeignPtr imgDat
    bitmapOfForeignPtr w h (BitmapFormat TopToBottom PxRGBA) ptr True
  {-# INLINE fromImageRGBA8 #-}
  
  
  {-| Creation of a brillo 'Picture' by promoting (through 'promoteImage')
  the 'PixelRGB8' image to 'PixelRGBA8' and calling 'fromImageRGBA8'.
  -}
  fromImageRGB8 :: Image PixelRGB8 -> Picture
  fromImageRGB8 = fromImageRGBA8 . promoteImage
  {-# INLINE fromImageRGB8 #-}
  
  
  {-| Creation of a brillo 'Picture' by promoting (through 'promoteImage')
  the 'PixelY8' image to 'PixelRGBA8' and calling 'fromImageRGBA8'.
  -}
  fromImageY8 :: Image Pixel8 -> Picture
  fromImageY8 = fromImageRGBA8 . promoteImage
  {-# INLINE fromImageY8 #-}
  
  
  {-| Creation of a brillo 'Picture' by promoting (through 'promoteImage')
  the 'PixelYA8' image to 'PixelRGBA8' and calling 'fromImageRGBA8'.
  -}
  fromImageYA8 :: Image PixelYA8 -> Picture
  fromImageYA8 = fromImageRGBA8 . promoteImage
  {-# INLINE fromImageYA8 #-}
  
  
  {-| Creation of a brillo 'Picture' by promoting (through 'promoteImage')
  the 'PixelYCbCr8' image to 'PixelRGBA8' and calling 'fromImageRGBA8'.
  -}
  fromImageYCbCr8 :: Image PixelYCbCr8 -> Picture
  fromImageYCbCr8 = fromImageRGB8 . convertImage
  {-# INLINE fromImageYCbCr8 #-}
  
  
  {-| Tries to load an image file into a Picture
    using 'readImage' from JuicyPixels.
    It means it'll try to successively read the content
    as an image in the following order,
    until it succeeds (or fails on all of them):
    jpeg, png, bmp, gif, hdr (the last two are not supported)
    This is handy when you don't know
    what format the image contained in the file is encoded with.
    If you know the format in advance,
    use 'loadBMP', 'loadJuicyJPG' or 'loadJuicyPNG'
  -}
  loadJuicy :: FilePath -> IO (Maybe Picture)
  loadJuicy = loadWith readImage
  {-# INLINE loadJuicy #-}
  
  
  loadJuicyWithMetadata :: FilePath -> IO (Maybe (Picture, Metadatas))
  loadJuicyWithMetadata = loadWithMetadata readImageWithMetadata
  {-# INLINE loadJuicyWithMetadata #-}
  
  
  loadJuicyJPG :: FilePath -> IO (Maybe Picture)
  loadJuicyJPG = loadWith readJpeg
  {-# INLINE loadJuicyJPG #-}
  
  
  loadJuicyPNG :: FilePath -> IO (Maybe Picture)
  loadJuicyPNG = loadWith readPng
  {-# INLINE loadJuicyPNG #-}
  
  
  loadWith ::
    (FilePath -> IO (Either String DynamicImage)) ->
    FilePath ->
    IO (Maybe Picture)
  loadWith reader fp = do
    eImg <- reader fp
    return $ either (const Nothing) fromDynamicImage eImg
  
  
  loadWithMetadata ::
    (FilePath -> IO (Either String (DynamicImage, Metadatas))) ->
    FilePath ->
    IO (Maybe (Picture, Metadatas))
  loadWithMetadata reader fp = do
    eImg <- reader fp
    return $
      either
        (const Nothing)
        (\(x, y) -> fmap (,y) (fromDynamicImage x))
        eImg
  