{-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} module Servant.JuicyPixels where import Codec.Picture import Codec.Picture.Bitmap import Codec.Picture.Gif import Codec.Picture.HDR import Codec.Picture.Jpg import Codec.Picture.Metadata import Codec.Picture.Png import Codec.Picture.Saving import Codec.Picture.Tga import Codec.Picture.Tiff import Codec.Picture.Types import qualified Data.ByteString.Lazy as BL import Data.Proxy import GHC.TypeLits import qualified Network.HTTP.Media as M import Servant.API data BMP instance Accept BMP where contentType _ = "image" M.// "bmp" instance MimeRender BMP DynamicImage where mimeRender _ = imageToBitmap instance BmpEncodable pixel => MimeRender BMP (Image pixel, Metadatas) where mimeRender _ (img, metadata) = encodeBitmapWithMetadata metadata img instance MimeUnrender BMP DynamicImage where mimeUnrender _ = decodeBitmap . BL.toStrict instance MimeUnrender BMP (DynamicImage, Metadatas) where mimeUnrender _ = decodeBitmapWithMetadata . BL.toStrict data GIF instance Accept GIF where contentType _ = "image" M.// "gif" instance MimeRender GIF DynamicImage where mimeRender _ = either error id . imageToGif instance MimeUnrender GIF DynamicImage where mimeUnrender _ = decodeGif . BL.toStrict instance MimeUnrender GIF (DynamicImage, Metadatas) where mimeUnrender _ = decodeGifWithMetadata . BL.toStrict data JPEG (quality :: Nat) instance (KnownNat quality, quality <= 100) => Accept (JPEG quality) where contentType _ = "image" M.// "jpeg" instance (KnownNat quality, quality <= 100) => MimeRender (JPEG quality) DynamicImage where mimeRender _ img = let quality = fromInteger $ natVal (Proxy :: Proxy quality) in imageToJpg quality img instance (KnownNat quality, quality <= 100, ColorSpaceConvertible a PixelYCbCr8) => MimeRender (JPEG quality) (Image a) where mimeRender _ = encodeJpegAtQuality quality . convertImage where quality = fromInteger $ natVal (Proxy :: Proxy quality) instance (KnownNat quality, quality <= 100, ColorSpaceConvertible a PixelYCbCr8) => MimeRender (JPEG quality) (Image a, Metadatas) where mimeRender _ (img, metadata) = encodeJpegAtQualityWithMetadata quality metadata $ convertImage img where quality = fromInteger $ natVal (Proxy :: Proxy quality) instance (KnownNat quality, quality <= 100) => MimeUnrender (JPEG quality) DynamicImage where mimeUnrender _ = decodeJpeg . BL.toStrict instance (KnownNat quality, quality <= 100) => MimeUnrender (JPEG quality) (DynamicImage, Metadatas) where mimeUnrender _ = decodeJpegWithMetadata . BL.toStrict data PNG instance Accept PNG where contentType _ = "image" M.// "png" instance MimeRender PNG DynamicImage where mimeRender _ = imageToPng instance PngSavable a => MimeRender PNG (Image a) where mimeRender _ = encodePng instance PngSavable a => MimeRender PNG (Image a, Metadatas) where mimeRender _ (img, metadata) = encodePngWithMetadata metadata img instance MimeUnrender PNG DynamicImage where mimeUnrender _ = decodePng . BL.toStrict instance MimeUnrender PNG (DynamicImage, Metadatas) where mimeUnrender _ = decodePngWithMetadata . BL.toStrict data TIFF instance Accept TIFF where contentType _ = "image" M.// "tiff" instance MimeRender TIFF DynamicImage where mimeRender _ = imageToTiff instance TiffSaveable a => MimeRender TIFF (Image a) where mimeRender _ = encodeTiff instance MimeUnrender TIFF DynamicImage where mimeUnrender _ = decodeTiff . BL.toStrict instance MimeUnrender TIFF (DynamicImage, Metadatas) where mimeUnrender _ = decodeTiffWithMetadata . BL.toStrict data RADIANCE instance Accept RADIANCE where contentType _ = "image" M.// "vnd.radiance" instance MimeRender RADIANCE DynamicImage where mimeRender _ = imageToRadiance instance a ~ PixelRGBF => MimeRender RADIANCE (Image a) where mimeRender _ = encodeHDR instance MimeUnrender RADIANCE DynamicImage where mimeUnrender _ = decodeHDR . BL.toStrict instance MimeUnrender RADIANCE (DynamicImage, Metadatas) where mimeUnrender _ = decodeHDRWithMetadata . BL.toStrict data TGA instance Accept TGA where contentType _ = "image" M.// "x-targa" instance MimeRender TGA DynamicImage where mimeRender _ = imageToTga instance TgaSaveable a => MimeRender TGA (Image a) where mimeRender _ = encodeTga instance MimeUnrender TGA DynamicImage where mimeUnrender _ = decodeTga . BL.toStrict instance MimeUnrender TGA (DynamicImage, Metadatas) where mimeUnrender _ = decodeTgaWithMetadata . BL.toStrict