Skip to content

Commit

Permalink
Grey to/from HSV conversions.
Browse files Browse the repository at this point in the history
Pixel conversions are now grouped in a single module, Vision.Image.Conversion.
  • Loading branch information
RaphaelJ committed Mar 8, 2015
1 parent 4ecf055 commit a641941
Show file tree
Hide file tree
Showing 14 changed files with 146 additions and 131 deletions.
49 changes: 49 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,55 @@ operators) ;

# Quick tour

## Modules

The library is divided in three main modules: `Vision.Primitive`, `Vision.Image`
and `Vision.Histogram`.

You can directly import sub-modules (such as `Vision.Image.Transform`), but the
backward-compatibility is *not* enforced. That is, some functions could be moved
to another sub-module in a newer backward-compatible advertised version.

### Vision.Primitive

`Vision.Primitive` contains types used all over the library, such as `Shape`
which is used to define shapes and indices in images and histograms.

The module is usually imported unqualified:

```haskell
import Vision.Primitive
```

### Vision.Image

`Vision.Image` contains functions and types to manage and transform images.

The module can be imported unqualified but it's often better use a qualified
import as some function names (such as `map`) can conflict with `Prelude` and
`Vision.Histogram`:

```haskell
import Vision.Image
-- or
import qualified Vision.Image as I
```

### Vision.Histogram

`Vision.Histogram` contains functions and types to create and compare
histograms.

The module can be imported unqualified but it's often better use a qualified
import as some function names (such as `map`) can conflict with `Prelude` and
`Vision.Image`:

```haskell
import Vision.Histogram
-- or
import qualified Vision.Histogram as H
```

## The Image type-class

Images implement the `Image` type-class.
Expand Down
3 changes: 3 additions & 0 deletions changelog
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
-*-change-log-*-

v0.2.1.0 March 2014
* Grey to HSV conversion.

v0.2.0.2 February 2014
* Minor documentation improvements.

Expand Down
7 changes: 2 additions & 5 deletions friday.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: friday
-- +-+------- breaking API changes
-- | | +----- non-breaking API additions
-- | | | +--- code changes with no API change
version: 0.2.0.2
version: 0.2.1.0
synopsis: A functional image processing library for Haskell.
homepage: https://github.com/RaphaelJ/friday
license: LGPL-3
Expand Down Expand Up @@ -47,24 +47,21 @@ library
Vision.Histogram
Vision.Image
Vision.Image.Class
Vision.Image.Conversion
Vision.Image.Grey
Vision.Image.Grey.Conversion
Vision.Image.Grey.Specialize
Vision.Image.Grey.Type
Vision.Image.Filter
Vision.Image.Filter.Internal
Vision.Image.HSV
Vision.Image.HSV.Conversion
Vision.Image.HSV.Specialize
Vision.Image.HSV.Type
Vision.Image.Interpolate
Vision.Image.Mutable
Vision.Image.RGBA
Vision.Image.RGBA.Conversion
Vision.Image.RGBA.Specialize
Vision.Image.RGBA.Type
Vision.Image.RGB
Vision.Image.RGB.Conversion
Vision.Image.RGB.Specialize
Vision.Image.RGB.Type
Vision.Image.Threshold
Expand Down
2 changes: 2 additions & 0 deletions src/Vision/Image.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
-- detailed usage and examples.
module Vision.Image (
module Vision.Image.Class
, module Vision.Image.Conversion
, module Vision.Image.Grey
, module Vision.Image.Filter
, module Vision.Image.HSV
Expand All @@ -27,6 +28,7 @@ module Vision.Image (
) where

import Vision.Image.Class
import Vision.Image.Conversion
import Vision.Image.Grey
import Vision.Image.Filter
import Vision.Image.HSV
Expand Down
3 changes: 0 additions & 3 deletions src/Vision/Image/Class.hs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,8 @@ module Vision.Image.Class (
, FunctorImage (..)
-- * Functions
, (!), (!?), nChannels, pixel
-- * Conversion
, Convertible (..), convert
) where

import Data.Convertible (Convertible (..), convert)
import Data.Int
import Data.Vector.Storable (Vector, generate, unfoldr)
import Data.Word
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,62 @@
{-# LANGUAGE BangPatterns
, MultiParamTypeClasses
, PatternGuards #-}
, MultiParamTypeClasses #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}

module Vision.Image.HSV.Conversion () where
-- 'Convertible' instances for conversions between pixel types.
module Vision.Image.Conversion (Convertible (..), convert) where

import Data.Convertible (Convertible (..), ConvertResult)
import Data.Convertible (Convertible (..), ConvertResult, convert)
import Data.Word

import qualified Data.Vector.Storable as VS

import Vision.Image.Grey.Type (GreyPixel (..))
import Vision.Image.HSV.Type (HSVPixel (..))
import Vision.Image.RGB.Type (RGBPixel (..))
import Vision.Image.RGB.Conversion ()
import Vision.Image.RGBA.Type (RGBAPixel (..))
import Vision.Image.RGBA.Conversion ()
import Vision.Image.RGB.Type (RGBPixel (..))

-- to Grey ---------------------------------------------------------------------

instance Convertible GreyPixel GreyPixel where
safeConvert = Right
{-# INLINE safeConvert #-}

instance Convertible HSVPixel GreyPixel where
safeConvert pix = (safeConvert pix :: ConvertResult RGBPixel)
>>= safeConvert

instance Convertible RGBAPixel GreyPixel where
safeConvert !(RGBAPixel r g b a) =
Right $ GreyPixel $ word8 $ int (rgbToGrey r g b) * int a `quot` 255
{-# INLINE safeConvert #-}

instance Convertible RGBPixel GreyPixel where
safeConvert !(RGBPixel r g b) =
Right $ GreyPixel $ rgbToGrey r g b
{-# INLINE safeConvert #-}

-- | Converts the colors to greyscale using the human eye colors perception.
rgbToGrey :: Word8 -> Word8 -> Word8 -> Word8
rgbToGrey !r !g !b = (redLookupTable VS.! int r)
+ (greenLookupTable VS.! int g)
+ (blueLookupTable VS.! int b)
{-# INLINE rgbToGrey #-}

redLookupTable, greenLookupTable, blueLookupTable :: VS.Vector Word8
redLookupTable = VS.generate 256 (\val -> round $ double val * 0.299)
greenLookupTable = VS.generate 256 (\val -> round $ double val * 0.587)
blueLookupTable = VS.generate 256 (\val -> round $ double val * 0.114)

-- to HSV ----------------------------------------------------------------------

instance Convertible HSVPixel HSVPixel where
safeConvert = Right
{-# INLINE safeConvert #-}

instance Convertible GreyPixel HSVPixel where
safeConvert pix = (safeConvert pix :: ConvertResult RGBPixel)
>>= safeConvert

instance Convertible RGBPixel HSVPixel where
-- Based on :
-- http://en.wikipedia.org/wiki/HSL_and_HSV#General_approach
Expand Down Expand Up @@ -47,10 +86,33 @@ instance Convertible RGBPixel HSVPixel where
sat !c v = word8 $ (c * 255) `quot` v

-- Keeps the value of the hue between [0, 179].
-- As the Hue's unit is 2°, 180 is equal to 360° and to 0.
-- As the Hue's unit is 2°, 180 is equal to 360° and to 0°.
fixHue !h | h < 0 = h + 180
| otherwise = h

instance Convertible RGBAPixel HSVPixel where
safeConvert pix = (safeConvert pix :: ConvertResult RGBPixel)
>>= safeConvert

-- to RGB ----------------------------------------------------------------------

instance Convertible RGBPixel RGBPixel where
safeConvert = Right
{-# INLINE safeConvert #-}

instance Convertible GreyPixel RGBPixel where
safeConvert !(GreyPixel pix) = Right $ RGBPixel pix pix pix
{-# INLINE safeConvert #-}

instance Convertible RGBAPixel RGBPixel where
safeConvert !(RGBAPixel r g b a) =
Right $ RGBPixel (withAlpha r) (withAlpha g) (withAlpha b)
where
!a' = int a
withAlpha !val = word8 $ int val * a' `quot` 255
{-# INLINE withAlpha #-}
{-# INLINE safeConvert #-}

instance Convertible HSVPixel RGBPixel where
-- Based on :
-- http://en.wikipedia.org/wiki/HSL_and_HSV#Converting_to_RGB
Expand Down Expand Up @@ -78,14 +140,29 @@ instance Convertible HSVPixel RGBPixel where
x2 d = (d * v' - d * m + h' * m - h' * v' + 30 * m) `quot` 30
{-# INLINE safeConvert #-}

instance Convertible RGBAPixel HSVPixel where
safeConvert pix = (safeConvert pix :: ConvertResult RGBPixel)
>>= safeConvert
-- to RGBA ---------------------------------------------------------------------

instance Convertible RGBAPixel RGBAPixel where
safeConvert = Right
{-# INLINE safeConvert #-}

instance Convertible GreyPixel RGBAPixel where
safeConvert !(GreyPixel pix) = Right $ RGBAPixel pix pix pix 255
{-# INLINE safeConvert #-}

instance Convertible HSVPixel RGBAPixel where
safeConvert pix = (safeConvert pix :: ConvertResult RGBPixel)
>>= safeConvert

instance Convertible RGBPixel RGBAPixel where
safeConvert !(RGBPixel r g b) = Right $ RGBAPixel r g b 255
{-# INLINE safeConvert #-}

-- -----------------------------------------------------------------------------

double :: Integral a => a -> Double
double = fromIntegral

int :: Integral a => a -> Int
int = fromIntegral

Expand Down
1 change: 0 additions & 1 deletion src/Vision/Image/Grey.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,5 @@ module Vision.Image.Grey (
module Vision.Image.Grey.Type
) where

import Vision.Image.Grey.Conversion ()
import Vision.Image.Grey.Specialize ()
import Vision.Image.Grey.Type
48 changes: 0 additions & 48 deletions src/Vision/Image/Grey/Conversion.hs

This file was deleted.

1 change: 0 additions & 1 deletion src/Vision/Image/HSV.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,5 @@ module Vision.Image.HSV (
module Vision.Image.HSV.Type
) where

import Vision.Image.HSV.Conversion ()
import Vision.Image.HSV.Specialize ()
import Vision.Image.HSV.Type
1 change: 0 additions & 1 deletion src/Vision/Image/RGB.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,5 @@ module Vision.Image.RGB (
module Vision.Image.RGB.Type
) where

import Vision.Image.RGB.Conversion ()
import Vision.Image.RGB.Specialize ()
import Vision.Image.RGB.Type
35 changes: 0 additions & 35 deletions src/Vision/Image/RGB/Conversion.hs

This file was deleted.

1 change: 0 additions & 1 deletion src/Vision/Image/RGBA.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,5 @@ module Vision.Image.RGBA (
module Vision.Image.RGBA.Type
) where

import Vision.Image.RGBA.Conversion ()
import Vision.Image.RGBA.Specialize ()
import Vision.Image.RGBA.Type

0 comments on commit a641941

Please sign in to comment.