packages feed

union-color-0.1.4.0: src/Data/Color/Internal/GrayScale.hs

{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}

module Data.Color.Internal.GrayScale where

import Data.Bits
import Data.Word
import Data.Int

import Data.Color.Internal

-- GRAY

data Gray d
	= GrayWord1_ Word8 | GrayWord2_ Word8 | GrayWord4_ Word8
	| GrayWord8_ Word8 | GrayWord16_ Word16 | GrayWord32_ Word32
	| GrayInt32_ Int32 | GrayDouble_ d
	deriving Show

{-# COMPLETE GrayWord1 #-}

pattern GrayWord1 :: RealFrac d => Word8 -> Gray d
pattern GrayWord1 g <- (grayToWord1 -> g)

grayWord1 :: Word8 -> Maybe (Gray d)
grayWord1 w
	| 0 <= w && w < 2 = Just $ GrayWord1_ w
	| otherwise = Nothing

grayToWord1 :: RealFrac d => Gray d -> Word8
grayToWord1 (GrayWord1_ g) = g
grayToWord1 (GrayWord2_ g) = g `shiftR` 1
grayToWord1 (GrayWord4_ g) = g `shiftR` 3
grayToWord1 (GrayWord8_ g) = g `shiftR` 7
grayToWord1 (GrayWord16_ g) = fromIntegral $ g `shiftR` 15
grayToWord1 (GrayWord32_ g) = fromIntegral $ g `shiftR` 31
grayToWord1 (GrayInt32_ g) = fromIntegral $ g `shiftR` 30
grayToWord1 (GrayDouble_ g) = fracToWord8 g `shiftR` 7

{-# COMPLETE GrayWord2 #-}

pattern GrayWord2 :: RealFrac d => Word8 -> Gray d
pattern GrayWord2 g <- (grayToWord2 -> g)

grayWord2 :: Word8 -> Maybe (Gray d)
grayWord2 g
	| 0 <= g && g < 4 = Just $ GrayWord2_ g
	| otherwise = Nothing

grayToWord2 :: RealFrac d => Gray d -> Word8
grayToWord2 (GrayWord1_ g) = g `shiftL` 1 .|. g
grayToWord2 (GrayWord2_ g) = g
grayToWord2 (GrayWord4_ g) = g `shiftR` 2
grayToWord2 (GrayWord8_ g) = g `shiftR` 6
grayToWord2 (GrayWord16_ g) = fromIntegral $ g `shiftR` 14
grayToWord2 (GrayWord32_ g) = fromIntegral $ g `shiftR` 30
grayToWord2 (GrayInt32_ g) = fromIntegral $ g `shiftR` 29
grayToWord2 (GrayDouble_ g) = fracToWord8 g `shiftR` 6

{-# COMPLETE GrayWord4 #-}

pattern GrayWord4 :: RealFrac d => Word8 -> Gray d
pattern GrayWord4 g <- (grayToWord4 -> g)

grayWord4 :: Word8 -> Maybe (Gray d)
grayWord4 g
	| 0 <= g && g < 16 = Just $ GrayWord4_ g
	| otherwise = Nothing

grayToWord4 :: RealFrac d => Gray d -> Word8
grayToWord4 (GrayWord1_ g) =
	g `shiftL` 3 .|. g `shiftL` 2 .|. g `shiftL` 1 .|. g
grayToWord4 (GrayWord2_ g) = g `shiftL` 2 .|. g
grayToWord4 (GrayWord4_ g) = g
grayToWord4 (GrayWord8_ g) = g `shiftR` 4
grayToWord4 (GrayWord16_ g) = fromIntegral $ g `shiftR` 12
grayToWord4 (GrayWord32_ g) = fromIntegral $ g `shiftR` 28
grayToWord4 (GrayInt32_ g) = fromIntegral $ g `shiftR` 27
grayToWord4 (GrayDouble_ g) = fracToWord8 g `shiftR` 4

{-# COMPLETE GrayWord8 #-}

pattern GrayWord8 :: RealFrac d => Word8 -> Gray d
pattern GrayWord8 x <- (fromGrayWord8 -> x) where
	GrayWord8 = GrayWord8_

fromGrayWord8 :: RealFrac d => Gray d -> Word8
fromGrayWord8 = \case
	GrayWord1_ x ->
		x `shiftL` 7 .|. x `shiftL` 6 .|.
		x `shiftL` 5 .|. x `shiftL` 4 .|.
		x `shiftL` 3 .|. x `shiftL` 2 .|.
		x `shiftL` 1 .|. x
	GrayWord2_ x ->
		x `shiftL` 6 .|. x `shiftL` 4 .|.
		x `shiftL` 2 .|. x
	GrayWord4_ x -> x `shiftL` 4 .|. x
	GrayWord8_ x -> x
	GrayWord16_ x -> fromIntegral $ x `shiftR` 8
	GrayWord32_ x -> fromIntegral $ x `shiftR` 24
	GrayInt32_ x -> fromIntegral $ x `shiftR` 23
	GrayDouble_ x -> fracToWord8 x

fracToWord8 :: RealFrac d => d -> Word8
fracToWord8 = round . (* 0xff)

{-# COMPLETE GrayWord16 #-}

pattern GrayWord16 :: RealFrac d => Word16 -> Gray d
pattern GrayWord16 x <- (grayToWord16 -> x) where
	GrayWord16 = GrayWord16_

grayToWord16 :: RealFrac d => Gray d -> Word16
grayToWord16 = \case
	GrayWord1_ x ->
		x' `shiftL` 15 .|. x' `shiftL` 14 .|.
		x' `shiftL` 13 .|. x' `shiftL` 12 .|.
		x' `shiftL` 11 .|. x' `shiftL` 10 .|.
		x' `shiftL` 9 .|. x' `shiftL` 8 .|.
		x' `shiftL` 7 .|. x' `shiftL` 6 .|.
		x' `shiftL` 5 .|. x' `shiftL` 4 .|.
		x' `shiftL` 3 .|. x' `shiftL` 2 .|.
		x' `shiftL` 1 .|. x'
		where x' = fromIntegral x
	GrayWord2_ x ->
		x' `shiftL` 14 .|. x' `shiftL` 12 .|.
		x' `shiftL` 10 .|. x' `shiftL` 8 .|.
		x' `shiftL` 6 .|. x' `shiftL` 4 .|.
		x' `shiftL` 2 .|. x'
		where x' = fromIntegral x
	GrayWord4_ x ->
		x' `shiftL` 12 .|. x' `shiftL` 8 .|. x' `shiftL` 4 .|. x'
		where x' = fromIntegral x
	GrayWord8_ x -> x' `shiftL` 8 .|. x' where x' = fromIntegral x
	GrayWord16_ x -> x
	GrayWord32_ x -> fromIntegral $ x `shiftR` 16
	GrayInt32_ x -> fromIntegral $ x `shiftR` 15
	GrayDouble_ x -> fracToWord16 x

fracToWord16 :: RealFrac d => d -> Word16
fracToWord16 = round . (* 0xffff)

{-# COMPLETE GrayWord32 #-}

pattern GrayWord32 :: RealFrac d => Word32 -> Gray d
pattern GrayWord32 x <- (grayToWord32 -> x) where
	GrayWord32 = GrayWord32_

grayToWord32 :: RealFrac d => Gray d -> Word32
grayToWord32 = \case
	GrayWord1_ x ->
		x' `shiftL` 31 .|. x' `shiftL` 30 .|.
		x' `shiftL` 29 .|. x' `shiftL` 28 .|.
		x' `shiftL` 27 .|. x' `shiftL` 26 .|.
		x' `shiftL` 25 .|. x' `shiftL` 24 .|.
		x' `shiftL` 23 .|. x' `shiftL` 22 .|.
		x' `shiftL` 21 .|. x' `shiftL` 20 .|.
		x' `shiftL` 19 .|. x' `shiftL` 18 .|.
		x' `shiftL` 17 .|. x' `shiftL` 16 .|.
		x' `shiftL` 15 .|. x' `shiftL` 14 .|.
		x' `shiftL` 13 .|. x' `shiftL` 12 .|.
		x' `shiftL` 11 .|. x' `shiftL` 10 .|.
		x' `shiftL` 9 .|. x' `shiftL` 8 .|.
		x' `shiftL` 7 .|. x' `shiftL` 6 .|.
		x' `shiftL` 5 .|. x' `shiftL` 4 .|.
		x' `shiftL` 3 .|. x' `shiftL` 2 .|.
		x' `shiftL` 1 .|. x'
		where x' = fromIntegral x
	GrayWord2_ x ->
		x' `shiftL` 30 .|. x' `shiftL` 28 .|.
		x' `shiftL` 26 .|. x' `shiftL` 24 .|.
		x' `shiftL` 22 .|. x' `shiftL` 20 .|.
		x' `shiftL` 18 .|. x' `shiftL` 16 .|.
		x' `shiftL` 14 .|. x' `shiftL` 12 .|.
		x' `shiftL` 10 .|. x' `shiftL` 8 .|.
		x' `shiftL` 6 .|. x' `shiftL` 4 .|.
		x' `shiftL` 2 .|. x'
		where x' = fromIntegral x
	GrayWord4_ x ->
		x' `shiftL` 28 .|. x' `shiftL` 24 .|.
		x' `shiftL` 20 .|. x' `shiftL` 16 .|.
		x' `shiftL` 12 .|. x' `shiftL` 8 .|.
		x' `shiftL` 4 .|. x'
		where x' = fromIntegral x
	GrayWord8_ x ->
		x' `shiftL` 24 .|. x' `shiftL` 16 .|. x' `shiftL` 8 .|. x'
		where x' = fromIntegral x
	GrayWord16_ x -> x' `shiftL` 16 .|. x' where x' = fromIntegral x
	GrayWord32_ x -> x
	GrayInt32_ x -> fromIntegral x `shiftL` 1
	GrayDouble_ x -> fracToWord32 x

fracToWord32 :: RealFrac d => d -> Word32
fracToWord32 = round . (* 0xffffffff)

{-# COMPLETE GrayInt32 #-}

pattern GrayInt32 :: RealFrac d => Int32 -> Gray d
pattern GrayInt32 x <- (grayToInt32 -> x) where
	GrayInt32 = GrayInt32_

grayToInt32 :: RealFrac d => Gray d -> Int32
grayToInt32 = \case
	GrayWord1_ x ->
		x' `shiftL` 30 .|. x' `shiftL` 29 .|.
		x' `shiftL` 28 .|. x' `shiftL` 27 .|.
		x' `shiftL` 26 .|. x' `shiftL` 25 .|.
		x' `shiftL` 24 .|. x' `shiftL` 23 .|.
		x' `shiftL` 22 .|. x' `shiftL` 21 .|.
		x' `shiftL` 20 .|. x' `shiftL` 19 .|.
		x' `shiftL` 18 .|. x' `shiftL` 17 .|.
		x' `shiftL` 16 .|. x' `shiftL` 15 .|.
		x' `shiftL` 14 .|. x' `shiftL` 13 .|.
		x' `shiftL` 12 .|. x' `shiftL` 11 .|.
		x' `shiftL` 10 .|. x' `shiftL` 9 .|.
		x' `shiftL` 8 .|. x' `shiftL` 7 .|.
		x' `shiftL` 6 .|. x' `shiftL` 5 .|.
		x' `shiftL` 4 .|. x' `shiftL` 3 .|.
		x' `shiftL` 2 .|. x' `shiftL` 1 .|. x'
		where x' = fromIntegral x
	GrayWord2_ x ->
		x' `shiftL` 29 .|. x' `shiftL` 27 .|.
		x' `shiftL` 25 .|. x' `shiftL` 23 .|.
		x' `shiftL` 21 .|. x' `shiftL` 19 .|.
		x' `shiftL` 17 .|. x' `shiftL` 15 .|.
		x' `shiftL` 13 .|. x' `shiftL` 11 .|.
		x' `shiftL` 9 .|. x' `shiftL` 7 .|.
		x' `shiftL` 5 .|. x' `shiftL` 3 .|.
		x' `shiftL` 1 .|. x' `shiftR` 1
		where x' = fromIntegral x
	GrayWord4_ x ->
		x' `shiftL` 27 .|. x' `shiftL` 23 .|.
		x' `shiftL` 19 .|. x' `shiftL` 15 .|.
		x' `shiftL` 11 .|. x' `shiftL` 7 .|.
		x' `shiftL` 3 .|. x' `shiftR` 1
		where x' = fromIntegral x
	GrayWord8_ x ->
		x' `shiftL` 23 .|. x' `shiftL` 15 .|.
		x' `shiftL` 7 .|. x' `shiftR` 1
		where x' = fromIntegral x
	GrayWord16_ x -> x' `shiftL` 15 .|. x' `shiftR` 1
		where x' = fromIntegral x
	GrayWord32_ x -> fromIntegral $ x `shiftR` 1
	GrayInt32_ x -> x
	GrayDouble_ x -> fracToInt32 x

fracToInt32 :: RealFrac d => d -> Int32
fracToInt32 = round . (* 0x7fffffff)

{-# COMPLETE GrayDouble #-}

pattern GrayDouble :: RealFrac d => d -> Gray d
pattern GrayDouble x <- (grayToFrac -> x)

grayDouble :: (Ord d, Num d) => d -> Maybe (Gray d)
grayDouble x
	| 0 <= x && x <= 1 = Just $ GrayDouble_ x
	| otherwise = Nothing

grayToFrac :: (Eq d, Fractional d) => Gray d -> d
grayToFrac = \case
	GrayWord1_ x -> word1ToFrac x
	GrayWord2_ x -> word2ToFrac x
	GrayWord4_ x -> word4ToFrac x
	GrayWord8_ x -> word8ToFrac x
	GrayWord16_ x -> word16ToFrac x
	GrayWord32_ x -> word32ToFrac x
	GrayInt32_ x -> int32ToFrac x
	GrayDouble_ x -> x

grayRealToFrac :: (Real d, Fractional d') => Gray d -> Gray d'
grayRealToFrac = \case
	GrayWord1_ x -> GrayWord1_ x
	GrayWord2_ x -> GrayWord2_ x
	GrayWord4_ x -> GrayWord4_ x
	GrayWord8_ x -> GrayWord8_ x
	GrayWord16_ x -> GrayWord16_ x
	GrayWord32_ x -> GrayWord32_ x
	GrayInt32_ x -> GrayInt32_ x
	GrayDouble_ x -> GrayDouble_ $ realToFrac x

word1ToFrac :: Fractional d => Word8 -> d
word1ToFrac = fromIntegral

word2ToFrac :: Fractional d => Word8 -> d
word2ToFrac = (/ 0x3) . fromIntegral

word4ToFrac :: Fractional d => Word8 -> d
word4ToFrac = (/ 0xf) . fromIntegral

word8ToFrac :: Fractional d => Word8 -> d
word8ToFrac = (/ 0xff) . fromIntegral

word16ToFrac :: Fractional d => Word16 -> d
word16ToFrac = (/ 0xffff) . fromIntegral

word32ToFrac :: Fractional d => Word32 -> d
word32ToFrac = (/ 0xffffffff) . fromIntegral

int32ToFrac :: Fractional d => Int32 -> d
int32ToFrac = (/ 0x7fffffff) . fromIntegral

-- GRAY ALPHA

data GrayAlpha d
	= GrayAlphaWord8_ Word8 Word8
	| GrayAlphaWord16_ Word16 Word16
	| GrayAlphaWord32_ Word32 Word32
	| GrayAlphaInt32_ Int32 Int32
	| GrayAlphaDouble_ d d
	deriving Show

{-# COMPLETE GrayAlphaWord8 #-}

pattern GrayAlphaWord8 :: RealFrac d => Word8 -> Word8 -> GrayAlpha d
pattern GrayAlphaWord8 x a <- (fromGrayAlphaWord8 -> (x, a)) where
	GrayAlphaWord8 = GrayAlphaWord8_

fromGrayAlphaWord8 :: RealFrac d => GrayAlpha d -> (Word8, Word8)
fromGrayAlphaWord8 = \case
	GrayAlphaWord8_ x a -> (x, a)
	GrayAlphaWord16_ x a ->
		(fromIntegral $ x `shiftR` 8, fromIntegral $ a `shiftR` 8)
	GrayAlphaWord32_ x a ->
		(fromIntegral $ x `shiftR` 24, fromIntegral $ a `shiftR` 24)
	GrayAlphaInt32_ x a ->
		(fromIntegral $ x `shiftR` 23, fromIntegral $ a `shiftR` 23)
	GrayAlphaDouble_ x a -> (fracToWord8 x, fracToWord8 a)

{-# COMPLETE GrayAlphaWord16 #-}

pattern GrayAlphaWord16 :: RealFrac d => Word16 -> Word16 -> GrayAlpha d
pattern GrayAlphaWord16 x a <- (fromGrayAlphaWord16 -> (x, a)) where
	GrayAlphaWord16 = GrayAlphaWord16_

fromGrayAlphaWord16 :: RealFrac d => GrayAlpha d -> (Word16, Word16)
fromGrayAlphaWord16 = \case
	GrayAlphaWord8_ (fromIntegral -> x) (fromIntegral -> a) ->
		(x `shiftL` 8 .|. x, a `shiftL` 8 .|. a)
	GrayAlphaWord16_ x a -> (x, a)
	GrayAlphaWord32_ x a ->
		(fromIntegral $ x `shiftR` 16, fromIntegral $ a `shiftR` 16)
	GrayAlphaInt32_ x a ->
		(fromIntegral $ x `shiftR` 15, fromIntegral $ a `shiftR` 15)
	GrayAlphaDouble_ x a -> (fracToWord16 x, fracToWord16 a)

{-# COMPLETE GrayAlphaWord32 #-}

pattern GrayAlphaWord32 :: RealFrac d => Word32 -> Word32 -> GrayAlpha d
pattern GrayAlphaWord32 x a <- (fromGrayAlphaWord32 -> (x, a)) where
	GrayAlphaWord32 = GrayAlphaWord32_

fromGrayAlphaWord32 :: RealFrac d => GrayAlpha d -> (Word32, Word32)
fromGrayAlphaWord32 = \case
	GrayAlphaWord8_ (fromIntegral -> x) (fromIntegral -> a) -> (
		x `shiftL` 24 .|. x `shiftL` 16 .|. x `shiftL` 8 .|. x,
		a `shiftL` 24 .|. a `shiftL` 16 .|. a `shiftL` 8 .|. a )
	GrayAlphaWord16_ (fromIntegral -> x) (fromIntegral -> a) ->
		(x `shiftL` 16 .|. x, a `shiftL` 16 .|. a)
	GrayAlphaWord32_ x a -> (x, a)
	GrayAlphaInt32_ (fromIntegral -> x) (fromIntegral -> a) ->
		(x `shiftL` 1 .|. x `shiftR` 31, a `shiftL` 1 .|. a `shiftR` 31)
	GrayAlphaDouble_ x a -> (fracToWord32 x, fracToWord32 a)

{-# COMPLETE GrayAlphaInt32 #-}

pattern GrayAlphaInt32 :: RealFrac d => Int32 -> Int32 -> GrayAlpha d
pattern GrayAlphaInt32 x a <- (fromGrayAlphaInt32 -> (x, a)) where
	GrayAlphaInt32 = GrayAlphaInt32_

fromGrayAlphaInt32 :: RealFrac d => GrayAlpha d -> (Int32, Int32)
fromGrayAlphaInt32 = \case
	GrayAlphaWord8_ (fromIntegral -> x) (fromIntegral -> a) -> (
		x `shiftL` 23 .|. x `shiftL` 15 .|.
		x `shiftL` 7 .|. x `shiftR` 1,
		a `shiftL` 23 .|. a `shiftL` 15 .|.
		a `shiftL` 7 .|. x `shiftR` 1 )
	GrayAlphaWord16_ (fromIntegral -> x) (fromIntegral -> a) -> (
		x `shiftL` 15 .|. x `shiftR` 1,
		a `shiftL` 15 .|. x `shiftR` 1 )
	GrayAlphaWord32_ x a ->
		(fromIntegral $ x `shiftR` 1, fromIntegral $ a `shiftR` 1)
	GrayAlphaInt32_ x a -> (x, a)
	GrayAlphaDouble_ x a -> (fracToInt32 x, fracToInt32 a)

{-# COMPLETE GrayAlphaDouble #-}

pattern GrayAlphaDouble :: RealFrac d => d -> d -> GrayAlpha d
pattern GrayAlphaDouble x a <- (grayAlphaToFrac -> (x, a))

grayAlphaDouble :: RealFrac d => d -> d -> Maybe (GrayAlpha d)
grayAlphaDouble x a
	| 0 <= x && x <= 1, 0 <= a && a <= 1 = Just $ GrayAlphaDouble_ x a
	| otherwise = Nothing

grayAlphaToFrac :: RealFrac d => GrayAlpha d -> (d, d)
grayAlphaToFrac = \case
	GrayAlphaWord8_ x a -> (word8ToFrac x, word8ToFrac a)
	GrayAlphaWord16_ x a -> (word16ToFrac x, word16ToFrac a)
	GrayAlphaWord32_ x a -> (word32ToFrac x, word32ToFrac a)
	GrayAlphaInt32_ x a -> (int32ToFrac x, int32ToFrac a)
	GrayAlphaDouble_ x a -> (x, a)

fromGrayAlpha :: GrayAlpha d -> (Gray d, Alpha d)
fromGrayAlpha = \case
	(GrayAlphaWord8_ x a) -> (GrayWord8_ x, AlphaWord8_ a)
	(GrayAlphaWord16_ x a) -> (GrayWord16_ x, AlphaWord16_ a)
	(GrayAlphaWord32_ x a) -> (GrayWord32_ x, AlphaWord32_ a)
	(GrayAlphaInt32_ x a) -> (GrayInt32_ x, AlphaInt32_ a)
	(GrayAlphaDouble_ x a) -> (GrayDouble_ x, AlphaDouble_ a)

toGrayAlpha :: RealFrac d => Gray d -> Alpha d -> GrayAlpha d
toGrayAlpha (GrayWord8_ x) (AlphaWord8 a) = GrayAlphaWord8 x a
toGrayAlpha (GrayWord16_ x) (AlphaWord16 a) = GrayAlphaWord16 x a
toGrayAlpha (GrayWord32_ x) (AlphaWord32 a) = GrayAlphaWord32 x a
toGrayAlpha (GrayInt32_ x) (AlphaInt32 a) = GrayAlphaInt32 x a
toGrayAlpha (GrayDouble_ x) (AlphaDouble a) = GrayAlphaDouble_ x a
toGrayAlpha (GrayWord8 x) (AlphaWord8 a) = GrayAlphaWord8 x a

grayAlphaRealToFrac :: (Real d, Fractional d') => GrayAlpha d -> GrayAlpha d'
grayAlphaRealToFrac = \case
	GrayAlphaWord8_ x a -> GrayAlphaWord8_ x a
	GrayAlphaWord16_ x a -> GrayAlphaWord16_ x a
	GrayAlphaWord32_ x a -> GrayAlphaWord32_ x a
	GrayAlphaInt32_ x a -> GrayAlphaInt32_ x a
	GrayAlphaDouble_ x a -> GrayAlphaDouble_ (realToFrac x) (realToFrac a)