-- | Utilities for converting pixel color values.
--
-- NOTE: These functions are not polymorphic in the Float type because
--       without assisatance, GHC does a bad job of converting Word8s 
--       to and from floats. 
--
module Data.Array.Repa.Algorithms.Pixel
        ( floatRmsOfRGB8
        , doubleRmsOfRGB8
        , floatLuminanceOfRGB8
        , doubleLuminanceOfRGB8
        , rgb8OfGreyFloat
        , rgb8OfGreyDouble
        , rgb8OfFloat
        , rgb8OfDouble)
where
import Data.Word


-- | Compute the root mean square of an RGB color. Result is in the range [0..1].
floatRmsOfRGB8 :: (Word8, Word8, Word8) -> Float
{-# INLINE floatRmsOfRGB8 #-}
floatRmsOfRGB8 :: (Word8, Word8, Word8) -> Float
floatRmsOfRGB8 (Word8
r, Word8
g, Word8
b)
 = let  r' :: Float
r'      = Int -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
r :: Int) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
255
        g' :: Float
g'      = Int -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
g :: Int) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
255
        b' :: Float
b'      = Int -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b :: Int) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
255
        s :: Float
s       = ((Float
r' Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
r') Float -> Float -> Float
forall a. Num a => a -> a -> a
+ (Float
g' Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
g') Float -> Float -> Float
forall a. Num a => a -> a -> a
+ (Float
b' Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
b')) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
3
   in   Float -> Float
forall a. Floating a => a -> a
sqrt Float
s


-- | Compute the root mean square of an RGB color. Result is in the range [0..1].
doubleRmsOfRGB8 :: (Word8, Word8, Word8) -> Float
{-# INLINE doubleRmsOfRGB8 #-}
doubleRmsOfRGB8 :: (Word8, Word8, Word8) -> Float
doubleRmsOfRGB8 (Word8
r, Word8
g, Word8
b)
 = let  r' :: Float
r'      = Int -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
r :: Int) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
255
        g' :: Float
g'      = Int -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
g :: Int) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
255
        b' :: Float
b'      = Int -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b :: Int) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
255
        s :: Float
s       = ((Float
r' Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
r') Float -> Float -> Float
forall a. Num a => a -> a -> a
+ (Float
g' Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
g') Float -> Float -> Float
forall a. Num a => a -> a -> a
+ (Float
b' Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
b')) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
3
   in   Float -> Float
forall a. Floating a => a -> a
sqrt Float
s


-- | Convert an RGB color to its luminance value. Result in the range [0..1].
floatLuminanceOfRGB8 :: (Word8, Word8, Word8) -> Float
{-# INLINE floatLuminanceOfRGB8 #-}
floatLuminanceOfRGB8 :: (Word8, Word8, Word8) -> Float
floatLuminanceOfRGB8 (Word8
r, Word8
g, Word8
b)
 = let  r' :: Float
r'      = Int -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
r :: Int) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
255
        g' :: Float
g'      = Int -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
g :: Int) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
255
        b' :: Float
b'      = Int -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b :: Int) Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
255
   in   Float
r' Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
0.3 Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
g' Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
0.59 Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
b' Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
0.11


-- | Convert an RGB color to its luminance value. Result in the range [0..1].
doubleLuminanceOfRGB8 :: (Word8, Word8, Word8) -> Double
{-# INLINE doubleLuminanceOfRGB8 #-}
doubleLuminanceOfRGB8 :: (Word8, Word8, Word8) -> Double
doubleLuminanceOfRGB8 (Word8
r, Word8
g, Word8
b)
 = let  r' :: Double
r'      = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
r :: Int) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
255
        g' :: Double
g'      = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
g :: Int) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
255
        b' :: Double
b'      = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b :: Int) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
255
   in   Double
r' Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
0.3 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
g' Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
0.59 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
b' Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
0.11


-- | Promote a value in the range [0..1] to a grey RGB8 color.
rgb8OfGreyFloat :: Float -> (Word8, Word8, Word8)
{-# INLINE rgb8OfGreyFloat #-}
rgb8OfGreyFloat :: Float -> (Word8, Word8, Word8)
rgb8OfGreyFloat Float
x
 = let  v :: Word8
v        = Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Float -> Int
forall a b. (RealFrac a, Integral b) => a -> b
truncate (Float
x Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
255) :: Int)
   in   (Word8
v, Word8
v, Word8
v)


-- | Promote a value in the range [0..1] to a grey RGB8 color.
rgb8OfGreyDouble :: Double -> (Word8, Word8, Word8)
{-# INLINE rgb8OfGreyDouble #-}
rgb8OfGreyDouble :: Double -> (Word8, Word8, Word8)
rgb8OfGreyDouble Double
x
 = let  v :: Word8
v        = Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Double -> Int
forall a b. (RealFrac a, Integral b) => a -> b
truncate (Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
255) :: Int)
   in   (Word8
v, Word8
v, Word8
v)


-- | Promote a tuple of color components to a RGB8 color. 
--   Each of the source components should be in the range [0..1].
rgb8OfFloat :: (Float, Float, Float) -> (Word8, Word8, Word8)
{-# INLINE rgb8OfFloat #-}
rgb8OfFloat :: (Float, Float, Float) -> (Word8, Word8, Word8)
rgb8OfFloat (Float
r, Float
g, Float
b)
 = let  r8 :: Word8
r8      = Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Float -> Int
forall a b. (RealFrac a, Integral b) => a -> b
truncate (Float
r Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
255) :: Int)
        g8 :: Word8
g8      = Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Float -> Int
forall a b. (RealFrac a, Integral b) => a -> b
truncate (Float
g Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
255) :: Int)
        b8 :: Word8
b8      = Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Float -> Int
forall a b. (RealFrac a, Integral b) => a -> b
truncate (Float
b Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
255) :: Int)
   in   (Word8
r8, Word8
g8, Word8
b8)


-- | Promote a tuple of color components to a RGB8 color. 
--   Each of the source components should be in the range [0..1].
rgb8OfDouble :: (Double, Double, Double) -> (Word8, Word8, Word8)
{-# INLINE rgb8OfDouble #-}
rgb8OfDouble :: (Double, Double, Double) -> (Word8, Word8, Word8)
rgb8OfDouble (Double
r, Double
g, Double
b)
 = let  r8 :: Word8
r8      = Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Double -> Int
forall a b. (RealFrac a, Integral b) => a -> b
truncate (Double
r Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
255) :: Int)
        g8 :: Word8
g8      = Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Double -> Int
forall a b. (RealFrac a, Integral b) => a -> b
truncate (Double
g Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
255) :: Int)
        b8 :: Word8
b8      = Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Double -> Int
forall a b. (RealFrac a, Integral b) => a -> b
truncate (Double
b Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
255) :: Int)
   in   (Word8
r8, Word8
g8, Word8
b8)