Basic image processing with JuicyPixels in Haskell
This is an unfinished Post
I will introduce some basic ways to read/write/manipulate image file with JuicyPixels.
Pixel!
Byte-level Manipulation in Haskell
In haskell, usually we use Data.ByteString
or Data.ByteString.Lazy
as a container of raw data. Which means we will use some thing like Word8
to present one byte and thus manipulate data byte by byte.
Additionally, since Word8
are an instance of type class Num
and Integral
, one could simply use
to handle bytes as integers. The module Data.ByteString
and Data.ByteString.Lazy
are both provide some functions to convert between ByteString
and [Word8]
.
Present Pixels in JuicyPixels
Pixel 是一個 type class 內涵一些 operation 和一個 associated type synonym - PixelBaseComponent
Firstly JuicyPixels provides several basic pixel types,
type Pixel8 = Word8
data PixelRGB8 = PixelRGB8 !Pixel8 !Pixel8 !Pixel8
data PixelRGBA8 = PixelRGBA8 !Pixel8 !Pixel8 !Pixel8 !Pixel8
data PixelCMYK8 = PixelCMYK8 !Pixel8 !Pixel8 !Pixel8 !Pixel8
However, this is
A type a
can be one kind of pixel if it: (1) is Storable
into Vector
; (2) is a number; (3) provides equality operator.
class ( Storable (PixelBaseComponent a)
, Num (PixelBaseComponent a)
, Eq a ) => Pixel a where
type PixelBaseComponent a :: *
pixelOpacity :: a -> PixelBaseComponent a
-- skipped
Load image with JuicyPixels
In JuicyPixels, …
Define Image
As its name implies, the Image
contains information of width and height and a Vector
of (some kind of) pixels. The detail of Vector
is beyond this post, the only thing we should know is that Vector
is just an efficient linear structure which will be used to preserve pixels.
data Image a = Image
{ imageWidth :: {-# UNPACK #-} !Int
, imageHeight :: {-# UNPACK #-} !Int
, imageData :: Vector (PixelBaseComponent a)
}
PS. About that {-# UNPACK #-}
, please read Unpacking strict fields
Load Image as DynamicImage
JuicyPixels provides functions to enable directly loading images or decoding loaded images, which should be ByteString
, into haskell. Either way the result will be presented by a DynamicImage
structure. As shown in following code, a DynamicImage
includes an Image
structure with corresponding pixel type. Please notice, here we only show the most common cases.