Safe Haskell | None |
---|
Main module for image import/export into various image formats.
To use the library without thinking about it, look after decodeImage
and
readImage
.
Generally, the read* functions read the images from a file and try to decode it, and the decode* functions try to decode a bytestring.
For an easy image writing use the saveBmpImage
, saveJpgImage
& savePngImage
functions
- readImage :: FilePath -> IO (Either String DynamicImage)
- decodeImage :: ByteString -> Either String DynamicImage
- pixelMap :: forall a b. (Pixel a, Pixel b) => (a -> b) -> Image a -> Image b
- generateImage :: forall a. Pixel a => (Int -> Int -> a) -> Int -> Int -> Image a
- generateFoldImage :: forall a acc. Pixel a => (acc -> Int -> Int -> (acc, a)) -> acc -> Int -> Int -> (acc, Image a)
- withImage :: forall m pixel. (Pixel pixel, PrimMonad m) => Int -> Int -> (Int -> Int -> m pixel) -> m (Image pixel)
- saveBmpImage :: String -> DynamicImage -> IO ()
- saveJpgImage :: Int -> FilePath -> DynamicImage -> IO ()
- savePngImage :: String -> DynamicImage -> IO ()
- saveTiffImage :: FilePath -> DynamicImage -> IO ()
- saveRadianceImage :: FilePath -> DynamicImage -> IO ()
- class BmpEncodable pixel
- writeBitmap :: BmpEncodable pixel => FilePath -> Image pixel -> IO ()
- encodeBitmap :: forall pixel. BmpEncodable pixel => Image pixel -> ByteString
- readBitmap :: FilePath -> IO (Either String DynamicImage)
- decodeBitmap :: ByteString -> Either String DynamicImage
- encodeDynamicBitmap :: DynamicImage -> Either String ByteString
- writeDynamicBitmap :: FilePath -> DynamicImage -> IO (Either String Bool)
- readGif :: FilePath -> IO (Either String DynamicImage)
- readGifImages :: FilePath -> IO (Either String [Image PixelRGB8])
- decodeGif :: ByteString -> Either String DynamicImage
- decodeGifImages :: ByteString -> Either String [Image PixelRGB8]
- readJpeg :: FilePath -> IO (Either String DynamicImage)
- decodeJpeg :: ByteString -> Either String DynamicImage
- encodeJpeg :: Image PixelYCbCr8 -> ByteString
- encodeJpegAtQuality :: Word8 -> Image PixelYCbCr8 -> ByteString
- class PngSavable a where
- encodePng :: Image a -> ByteString
- readPng :: FilePath -> IO (Either String DynamicImage)
- decodePng :: ByteString -> Either String DynamicImage
- writePng :: PngSavable pixel => FilePath -> Image pixel -> IO ()
- encodeDynamicPng :: DynamicImage -> Either String ByteString
- writeDynamicPng :: FilePath -> DynamicImage -> IO (Either String Bool)
- readTiff :: FilePath -> IO (Either String DynamicImage)
- class Pixel px => TiffSaveable px
- decodeTiff :: ByteString -> Either String DynamicImage
- encodeTiff :: forall px. TiffSaveable px => Image px -> ByteString
- writeTiff :: TiffSaveable pixel => FilePath -> Image pixel -> IO ()
- readHDR :: FilePath -> IO (Either String DynamicImage)
- decodeHDR :: ByteString -> Either String DynamicImage
- encodeHDR :: Image PixelRGBF -> ByteString
- writeHDR :: FilePath -> Image PixelRGBF -> IO ()
- data Image a = Image {
- imageWidth :: !Int
- imageHeight :: !Int
- imageData :: Vector (PixelBaseComponent a)
- data DynamicImage
- = ImageY8 (Image Pixel8)
- | ImageY16 (Image Pixel16)
- | ImageYF (Image PixelF)
- | ImageYA8 (Image PixelYA8)
- | ImageYA16 (Image PixelYA16)
- | ImageRGB8 (Image PixelRGB8)
- | ImageRGB16 (Image PixelRGB16)
- | ImageRGBF (Image PixelRGBF)
- | ImageRGBA8 (Image PixelRGBA8)
- | ImageRGBA16 (Image PixelRGBA16)
- | ImageYCbCr8 (Image PixelYCbCr8)
- | ImageCMYK8 (Image PixelCMYK8)
- | ImageCMYK16 (Image PixelCMYK16)
- class (Storable (PixelBaseComponent a), Num (PixelBaseComponent a), Eq a) => Pixel a where
- type PixelBaseComponent a :: *
- mixWith :: (Int -> PixelBaseComponent a -> PixelBaseComponent a -> PixelBaseComponent a) -> a -> a -> a
- componentCount :: a -> Int
- colorMap :: (PixelBaseComponent a -> PixelBaseComponent a) -> a -> a
- pixelBaseIndex :: Image a -> Int -> Int -> Int
- mutablePixelBaseIndex :: MutableImage s a -> Int -> Int -> Int
- pixelAt :: Image a -> Int -> Int -> a
- readPixel :: PrimMonad m => MutableImage (PrimState m) a -> Int -> Int -> m a
- writePixel :: PrimMonad m => MutableImage (PrimState m) a -> Int -> Int -> a -> m ()
- unsafePixelAt :: Vector (PixelBaseComponent a) -> Int -> a
- unsafeReadPixel :: PrimMonad m => STVector (PrimState m) (PixelBaseComponent a) -> Int -> m a
- unsafeWritePixel :: PrimMonad m => STVector (PrimState m) (PixelBaseComponent a) -> Int -> a -> m ()
- type Pixel8 = Word8
- type Pixel16 = Word16
- type PixelF = Float
- data PixelYA8 = PixelYA8 !Pixel8 !Pixel8
- data PixelYA16 = PixelYA16 !Pixel16 !Pixel16
- data PixelRGB8 = PixelRGB8 !Pixel8 !Pixel8 !Pixel8
- data PixelRGB16 = PixelRGB16 !Pixel16 !Pixel16 !Pixel16
- data PixelRGBF = PixelRGBF !PixelF !PixelF !PixelF
- data PixelRGBA8 = PixelRGBA8 !Pixel8 !Pixel8 !Pixel8 !Pixel8
- data PixelRGBA16 = PixelRGBA16 !Pixel16 !Pixel16 !Pixel16 !Pixel16
- data PixelYCbCr8 = PixelYCbCr8 !Pixel8 !Pixel8 !Pixel8
- data PixelCMYK8 = PixelCMYK8 !Pixel8 !Pixel8 !Pixel8 !Pixel8
- data PixelCMYK16 = PixelCMYK16 !Pixel16 !Pixel16 !Pixel16 !Pixel16
Generic functions
readImage :: FilePath -> IO (Either String DynamicImage)Source
Load an image file without even thinking about it, it does everything
as decodeImage
decodeImage :: ByteString -> Either String DynamicImageSource
If you want to decode an image in a bytestring without even thinking in term of format or whatever, this is the function to use. It will try to decode in each known format and if one decoding succeed will return the decoded image in it's own colorspace
pixelMap :: forall a b. (Pixel a, Pixel b) => (a -> b) -> Image a -> Image bSource
map
equivalent for an image, working at the pixel level.
Little example : a brightness function for an rgb image
brightnessRGB8 :: Int -> Image PixelRGB8 -> Image PixelRGB8 brightnessRGB8 add = pixelMap brightFunction where up v = fromIntegral (fromIntegral v + add) brightFunction (PixelRGB8 r g b) = PixelRGB8 (up r) (up g) (up b)
:: forall a . Pixel a | |
=> (Int -> Int -> a) | Generating function, with |
-> Int | Width in pixels |
-> Int | Height in pixels |
-> Image a |
Create an image given a function to generate pixels. The function will receive value from 0 to width-1 for the x parameter and 0 to height-1 for the y parameter. The coordinate 0,0 is the upper left corner of the image, and (width-1, height-1) the lower right corner.
for example, to create a small gradient image :
imageCreator :: String -> Image PixelRGB8 imageCreator path = writePng path $ generateImage pixelRenderer 250 300 where pixelRenderer x y = PixelRGB8 x y 128
:: forall a acc . Pixel a | |
=> (acc -> Int -> Int -> (acc, a)) | Function taking the state, x and y |
-> acc | Initial state |
-> Int | Width in pixels |
-> Int | Height in pixels |
-> (acc, Image a) |
Create an image given a function to generate pixels. The function will receive value from 0 to width-1 for the x parameter and 0 to height-1 for the y parameter. The coordinate 0,0 is the upper left corner of the image, and (width-1, height-1) the lower right corner.
the acc parameter is a user defined one.
The function is called for each pixel in the line from left to right (0 to width - 1) and for each line (0 to height - 1).
:: forall m pixel . (Pixel pixel, PrimMonad m) | |
=> Int | Image width |
-> Int | Image height |
-> (Int -> Int -> m pixel) | Generating functions |
-> m (Image pixel) |
Create an image using a monadic initializer function. The function will receive value from 0 to width-1 for the x parameter and 0 to height-1 for the y parameter. The coordinate 0,0 is the upper left corner of the image, and (width-1, height-1) the lower right corner.
The function is called for each pixel in the line from left to right (0 to width - 1) and for each line (0 to height - 1).
Generic image writing
saveBmpImage :: String -> DynamicImage -> IO ()Source
Save an image to a '.bmp' file, will do everything it can to save an image.
saveJpgImage :: Int -> FilePath -> DynamicImage -> IO ()Source
Save an image to a '.jpg' file, will do everything it can to save an image.
savePngImage :: String -> DynamicImage -> IO ()Source
Save an image to a '.png' file, will do everything it can to save an image. For example, a simple transcoder to png
transcodeToPng :: FilePath -> FilePath -> IO () transcodeToPng pathIn pathOut = do eitherImg <- readImage pathIn case eitherImg of Left _ -> return () Right img -> savePngImage pathOut img
saveTiffImage :: FilePath -> DynamicImage -> IO ()Source
Save an image to a '.tiff' file, will do everything it can to save an image.
saveRadianceImage :: FilePath -> DynamicImage -> IO ()Source
Save an image to a '.hdr' file, will do everything it can to save an image.
Specific image format functions
Bitmap handling
class BmpEncodable pixel Source
All the instance of this class can be written as a bitmap file using this library.
writeBitmap :: BmpEncodable pixel => FilePath -> Image pixel -> IO ()Source
Write an image in a file use the bitmap format.
encodeBitmap :: forall pixel. BmpEncodable pixel => Image pixel -> ByteStringSource
Encode an image into a bytestring in .bmp format ready to be written on disk.
readBitmap :: FilePath -> IO (Either String DynamicImage)Source
Try to load a .bmp file. The colorspace would be RGB or RGBA
decodeBitmap :: ByteString -> Either String DynamicImageSource
Try to decode a bitmap image. Right now this function can output the following pixel types :
- PixelRGB8
encodeDynamicBitmap :: DynamicImage -> Either String ByteStringSource
Encode a dynamic image in bmp if possible, supported pixel type are :
- RGB8
- RGBA8
- Y8
writeDynamicBitmap :: FilePath -> DynamicImage -> IO (Either String Bool)Source
Write a dynamic image in a .bmp image file if possible. The same restriction as encodeDynamicBitmap apply.
Gif handling
readGif :: FilePath -> IO (Either String DynamicImage)Source
Helper function trying to load a gif file from a file on disk.
readGifImages :: FilePath -> IO (Either String [Image PixelRGB8])Source
Helper function trying to load all the images of an animated gif file.
decodeGif :: ByteString -> Either String DynamicImageSource
Transform a raw gif image to an image, witout modifying the pixels. This function can output the following pixel types :
- PixelRGB8
decodeGifImages :: ByteString -> Either String [Image PixelRGB8]Source
Transform a raw gif to a list of images, representing all the images of an animation.
Jpeg handling
readJpeg :: FilePath -> IO (Either String DynamicImage)Source
Try to load a jpeg file and decompress. The colorspace is still
YCbCr if you want to perform computation on the luma part. You can
convert it to RGB using colorSpaceConversion
decodeJpeg :: ByteString -> Either String DynamicImageSource
Try to decompress a jpeg file and decompress. The colorspace is still
YCbCr if you want to perform computation on the luma part. You can
convert it to RGB using convertImage
from the ColorSpaceConvertible
typeclass.
This function can output the following pixel types :
- PixelY8
- PixelYCbCr8
encodeJpeg :: Image PixelYCbCr8 -> ByteStringSource
Encode an image in jpeg at a reasonnable quality level.
If you want better quality or reduced file size, you should
use encodeJpegAtQuality
:: Word8 | Quality factor |
-> Image PixelYCbCr8 | Image to encode |
-> ByteString | Encoded JPEG |
Function to call to encode an image to jpeg. The quality factor should be between 0 and 100 (100 being the best quality).
Png handling
class PngSavable a whereSource
Encode an image into a png if possible.
encodePng :: Image a -> ByteStringSource
Transform an image into a png encoded bytestring, ready to be written as a file.
readPng :: FilePath -> IO (Either String DynamicImage)Source
Helper function trying to load a png file from a file on disk.
decodePng :: ByteString -> Either String DynamicImageSource
Transform a raw png image to an image, without modifying the underlying pixel type. If the image is greyscale and < 8 bits, a transformation to RGBA8 is performed. This should change in the future. The resulting image let you manage the pixel types.
This function can output the following pixel types :
- PixelY8
- PixelY16
- PixelYA8
- PixelYA16
- PixelRGB8
- PixelRGB16
- PixelRGBA8
- PixelRGBA16
writePng :: PngSavable pixel => FilePath -> Image pixel -> IO ()Source
Helper function to directly write an image as a png on disk.
encodeDynamicPng :: DynamicImage -> Either String ByteStringSource
Encode a dynamic image in bmp if possible, supported pixel type are :
- Y8
- Y16
- YA8
- YA16
- RGB8
- RGB16
- RGBA8
- RGBA16
writeDynamicPng :: FilePath -> DynamicImage -> IO (Either String Bool)Source
Write a dynamic image in a .png image file if possible. The same restriction as encodeDynamicPng apply.
Tiff handling
readTiff :: FilePath -> IO (Either String DynamicImage)Source
Helper function trying to load tiff file from a file on disk.
class Pixel px => TiffSaveable px Source
Class defining which pixel types can be serialized in a Tiff file.
decodeTiff :: ByteString -> Either String DynamicImageSource
Transform a raw tiff image to an image, without modifying the underlying pixel type.
This function can output the following pixel types :
- PixelY8
- PixelY16
- PixelRGB8
- PixelRGB16
- PixelCMYK8
- PixelCMYK16
encodeTiff :: forall px. TiffSaveable px => Image px -> ByteStringSource
Transform an image into a Tiff encoded bytestring, reade to be written as a file.
writeTiff :: TiffSaveable pixel => FilePath -> Image pixel -> IO ()Source
Helper function to directly write an image as a tiff on disk.
HDR (Radiance/RGBE) handling
readHDR :: FilePath -> IO (Either String DynamicImage)Source
Try to load a .pic file. The colorspace can only be RGB with floating point precision.
decodeHDR :: ByteString -> Either String DynamicImageSource
Decode an HDR (radiance) image, the resulting pixel type can be :
- PixelRGBF
encodeHDR :: Image PixelRGBF -> ByteStringSource
Encode an High dynamic range image into a radiance image file format.
writeHDR :: FilePath -> Image PixelRGBF -> IO ()Source
Write an High dynamic range image into a radiance image file on disk.
Image types and pixel types
Image
Image or pixel buffer, the coordinates are assumed to start from the upper-left corner of the image, with the horizontal position first, then the vertical one.
Image | |
|
data DynamicImage Source
Type allowing the loading of an image with different pixel structures
ImageY8 (Image Pixel8) | A greyscale image. |
ImageY16 (Image Pixel16) | A greyscale image with 16bit components |
ImageYF (Image PixelF) | A greyscale HDR image |
ImageYA8 (Image PixelYA8) | An image in greyscale with an alpha channel. |
ImageYA16 (Image PixelYA16) | An image in greyscale with alpha channel on 16 bits. |
ImageRGB8 (Image PixelRGB8) | An image in true color. |
ImageRGB16 (Image PixelRGB16) | An image in true color with 16bit depth. |
ImageRGBF (Image PixelRGBF) | An image with HDR pixels |
ImageRGBA8 (Image PixelRGBA8) | An image in true color and an alpha channel. |
ImageRGBA16 (Image PixelRGBA16) | A true color image with alpha on 16 bits. |
ImageYCbCr8 (Image PixelYCbCr8) | An image in the colorspace used by Jpeg images. |
ImageCMYK8 (Image PixelCMYK8) | An image in the colorspace CMYK |
ImageCMYK16 (Image PixelCMYK16) | An image in the colorspace CMYK and 16 bots precision |
Pixels
class (Storable (PixelBaseComponent a), Num (PixelBaseComponent a), Eq a) => Pixel a whereSource
Definition of pixels used in images. Each pixel has a color space, and a representative component (Word8 or Float).
type PixelBaseComponent a :: *Source
Type of the pixel component, classical images would have Word8 type as their PixelBaseComponent, HDR image would have Float for instance
mixWith :: (Int -> PixelBaseComponent a -> PixelBaseComponent a -> PixelBaseComponent a) -> a -> a -> aSource
Call the function for every component of the pixels. For example for RGB pixels mixWith is declared like this :
mixWith f (PixelRGB8 ra ga ba) (PixelRGB8 rb gb bb) = PixelRGB8 (f 0 ra rb) (f 1 ga gb) (f 2 ba bb)
componentCount :: a -> IntSource
Return the number of component of the pixel
colorMap :: (PixelBaseComponent a -> PixelBaseComponent a) -> a -> aSource
Apply a function to all color component of a pixel.
pixelBaseIndex :: Image a -> Int -> Int -> IntSource
Calculate the index for the begining of the pixel
mutablePixelBaseIndex :: MutableImage s a -> Int -> Int -> IntSource
Calculate theindex for the begining of the pixel at position x y
pixelAt :: Image a -> Int -> Int -> aSource
Extract a pixel at a given position, (x, y), the origin is assumed to be at the corner top left, positive y to the bottom of the image
readPixel :: PrimMonad m => MutableImage (PrimState m) a -> Int -> Int -> m aSource
Same as pixelAt but for mutable images.
writePixel :: PrimMonad m => MutableImage (PrimState m) a -> Int -> Int -> a -> m ()Source
Write a pixel in a mutable image at position x y
unsafePixelAt :: Vector (PixelBaseComponent a) -> Int -> aSource
Unsafe version of pixelAt, read a pixel at the given index without bound checking (if possible). The index is expressed in number (PixelBaseComponent a)
unsafeReadPixel :: PrimMonad m => STVector (PrimState m) (PixelBaseComponent a) -> Int -> m aSource
Unsafe version of readPixel, read a pixel at the given position without bound checking (if possible). The index is expressed in number (PixelBaseComponent a)
unsafeWritePixel :: PrimMonad m => STVector (PrimState m) (PixelBaseComponent a) -> Int -> a -> m ()Source
Unsafe version of writePixel, write a pixel at the given position without bound checking. This can be _really_ unsafe. The index is expressed in number (PixelBaseComponent a)
The following graph describe the differents way to convert between pixel types,
- Nodes describe pixel type
- Arrows describe functions
Floating greyscale value, the 0 to 255 8 bit range maps to 0 to 1 in this floating version
Pixel type storing Luminance (Y) and alpha information on 8 bits. Value are stored in the following order :
- Luminance
- Alpha
Pixel type storing Luminance (Y) and alpha information on 16 bits. Value are stored in the following order :
- Luminance
- Alpha
Pixel type storing classic pixel on 8 bits Value are stored in the following order :
- Red
- Green
- Blue
data PixelRGB16 Source
Pixel type storing pixels on 16 bits Value are stored in the following order :
- Red
- Green
- Blue
Pixel type storing HDR pixel on 32 bits float Value are stored in the following order :
- Red
- Green
- Blue
data PixelRGBA8 Source
Pixel type storing a classic pixel, with an alpha component. Values are stored in the following order
- Red
- Green
- Blue
- Alpha
data PixelRGBA16 Source
Pixel type storing a RGB information with an alpha channel on 16 bits. Values are stored in the following order
- Red
- Green
- Blue
- Alpha
data PixelYCbCr8 Source
Pixel storing data in the YCbCr colorspace, value are stored in the following order :
- Y (luminance)
- Cr
- Cb
data PixelCMYK8 Source
Pixel storing data in the CMYK colorspace. value are stored in the following order :
- Cyan
- Magenta
- Yellow
- Black
data PixelCMYK16 Source
Pixel storing data in the CMYK colorspace. value are stored in the following order :
- Cyan
- Magenta
- Yellow
- Black