{-# OPTIONS_GHC -fno-warn-orphans #-} {-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE ViewPatterns #-} #if __GLASGOW_HASKELL__ >= 800 {-# OPTIONS_GHC -Wno-redundant-constraints #-} {-# LANGUAGE MonoLocalBinds #-} #endif -- | -- Module : Graphics.ColorSpace -- Copyright : (c) Alexey Kuleshevich 2018-2019 -- License : BSD3 -- Maintainer : Alexey Kuleshevich -- Stability : experimental -- Portability : non-portable -- module Graphics.ColorSpace ( -- * Pixels -- ** Family of Pixels -- | Pixel is a type family for all available color spaces. Below is the -- listed of all class instances, that pixels are installed in, as well as all -- pixel constructors. -- -- >>> :t (PixelY 0) -- Black pixel in Luma -- (PixelY 0) :: Num e => Pixel Y e -- >>> PixelRGB 255 0 0 :: Pixel RGB Word8 -- Red pixel in RGB -- -- >>> PixelRGB 1 0 0 :: Pixel RGB Double -- Same red pixel in RGB with Double precision. -- -- >>> (PixelRGB 255 0 0 :: Pixel RGB Word8) == (toWord8 <$> (PixelRGB 1 0 0 :: Pixel RGB Double)) -- True -- Pixel(..) , ColorSpace(..) , AlphaSpace(..) -- ** Luma (gray scale) -- | Conversion to Luma from other color spaces. , toPixelY , toPixelYA -- ** RGB -- | Conversion to RGB from other color spaces. , toPixelRGB , toPixelRGBA -- ** HSI -- | Conversion to HSI from other color spaces. , toPixelHSI , toPixelHSIA -- ** CMYK -- | Conversion to CMYK from other color spaces. , toPixelCMYK , toPixelCMYKA -- ** YCbCr -- | Conversion to YCbCr from other color spaces. , toPixelYCbCr , toPixelYCbCrA -- ** Binary -- | This is a Binary colorspace, pixel's of which can be created using -- these __/constructors/__: -- -- [@'on'@] Represents value @1@ or 'True'. It's a foreground pixel and is -- displayed in black. -- -- [@'off'@] Represents value @0@ or 'False'. It's a background pixel and is -- displayed in white. -- -- Note, that values are inverted before writing to or reading from file, since -- grayscale images represent black as a @0@ value and white as @1@ on a -- @[0,1]@ scale. -- -- Binary pixels also behave as binary numbers with a size of 1-bit, for instance: -- -- >>> on + on -- equivalent to: 1 .|. 1 -- -- >>> (on + on) * off -- equivalent to: (1 .|. 1) .&. 0 -- -- >>> (on + on) - on -- -- , toPixelBinary , fromPixelBinary , module Graphics.ColorSpace.Binary -- ** Complex , module Graphics.ColorSpace.Complex -- ** X , toPixelsX , fromPixelsX -- * ColorSpace -- ** Operations on Pixels , eqTolPx -- ** Luma ,Y(..), YA(..), ToY, ToYA, -- ** RGB RGB(..), RGBA(..), ToRGB, ToRGBA, -- ** HSI HSI(..), HSIA(..), ToHSI, ToHSIA, -- ** CMYK CMYK(..), CMYKA(..), ToCMYK, ToCMYKA, -- ** YCbCr YCbCr(..), YCbCrA(..), ToYCbCr, ToYCbCrA, -- ** X X(..), -- * Precision -- ** Pixel Elevator(..), toWord8, toWord16, toWord32, toWord64, toFloat, toDouble, fromDouble, -- ** Componenet Word8, Word16, Word32, Word64 ) where import Data.Word import Graphics.ColorSpace.Binary import Graphics.ColorSpace.CMYK import Graphics.ColorSpace.Complex import Graphics.ColorSpace.HSI import Graphics.ColorSpace.Internal import Graphics.ColorSpace.RGB import Graphics.ColorSpace.X import Graphics.ColorSpace.Y import Graphics.ColorSpace.YCbCr -- -- Binary: -- | Convert to a `Binary` pixel. toPixelBinary :: ColorSpace cs e => Pixel cs e -> Pixel X Bit toPixelBinary px = if px == 0 then on else off -- | Convert a Binary pixel to Luma pixel fromPixelBinary :: Pixel X Bit -> Pixel Y Word8 fromPixelBinary b = PixelY $ if isOn b then minBound else maxBound {-# INLINE fromPixelBinary #-} -- | Check weather two Pixels are equal within a tolerance. Useful for comparing -- pixels with `Float` or `Double` precision. eqTolPx :: (ColorSpace cs e, Ord e) => e -> Pixel cs e -> Pixel cs e -> Bool eqTolPx !tol = foldlPx2 comp True where comp !acc !e1 !e2 = acc && max e1 e2 - min e1 e2 <= tol {-# INLINE comp #-} {-# INLINE eqTolPx #-} -- ToY -- | Conversion to Luma color space. class ColorSpace cs e => ToY cs e where -- | Convert a pixel to Luma pixel. toPixelY :: Pixel cs e -> Pixel Y Double instance Elevator e => ToY X e where toPixelY (PixelX y) = PixelY $ eToDouble y {-# INLINE toPixelY #-} instance Elevator e => ToY Y e where toPixelY (PixelY y) = PixelY $ eToDouble y {-# INLINE toPixelY #-} instance Elevator e => ToY YA e where toPixelY (PixelYA y _) = PixelY $ eToDouble y {-# INLINE toPixelY #-} -- | Computes Luma: @ Y' = 0.299 * R' + 0.587 * G' + 0.114 * B' @ instance Elevator e => ToY RGB e where toPixelY (toDouble -> PixelRGB r g b) = PixelY (0.299*r + 0.587*g + 0.114*b) {-# INLINE toPixelY #-} instance Elevator e => ToY RGBA e where toPixelY = toPixelY . dropAlpha {-# INLINE toPixelY #-} instance Elevator e => ToY HSI e where toPixelY = toPixelY . toPixelRGB . toDouble {-# INLINE toPixelY #-} instance Elevator e => ToY HSIA e where toPixelY = toPixelY . dropAlpha {-# INLINE toPixelY #-} instance Elevator e => ToY CMYK e where toPixelY = toPixelY . toPixelRGB . toDouble {-# INLINE toPixelY #-} instance Elevator e => ToY CMYKA e where toPixelY = toPixelY . toPixelRGB . toDouble . dropAlpha {-# INLINE toPixelY #-} instance Elevator e => ToY YCbCr e where toPixelY (PixelYCbCr y _ _) = PixelY $ eToDouble y {-# INLINE toPixelY #-} instance Elevator e => ToY YCbCrA e where toPixelY (PixelYCbCrA y _ _ _) = PixelY $ eToDouble y {-# INLINE toPixelY #-} -- ToYA -- | Conversion to Luma from another color space. class ToY cs e => ToYA cs e where -- | Convert a pixel to Luma pixel with Alpha. toPixelYA :: Pixel cs e -> Pixel YA Double toPixelYA = addAlpha 1 . toPixelY {-# INLINE toPixelYA #-} instance ToYA X Bit where toPixelYA (PixelX y) = PixelYA (eToDouble y) 1 {-# INLINE toPixelYA #-} instance ToY Y e => ToYA Y e instance Elevator e => ToYA YA e where toPixelYA = toDouble {-# INLINE toPixelYA #-} instance ToY RGB e => ToYA RGB e instance Elevator e => ToYA RGBA e where toPixelYA !px = addAlpha (eToDouble $ getAlpha px) (toPixelY (dropAlpha px)) {-# INLINE toPixelYA #-} instance ToY HSI e => ToYA HSI e instance Elevator e => ToYA HSIA e where toPixelYA !px = addAlpha (eToDouble $ getAlpha px) (toPixelY (dropAlpha px)) {-# INLINE toPixelYA #-} instance ToY CMYK e => ToYA CMYK e instance Elevator e => ToYA CMYKA e where toPixelYA !px = addAlpha (eToDouble $ getAlpha px) (toPixelY (dropAlpha px)) {-# INLINE toPixelYA #-} instance ToY YCbCr e => ToYA YCbCr e instance Elevator e => ToYA YCbCrA e where toPixelYA !px = addAlpha (eToDouble $ getAlpha px) (toPixelY (dropAlpha px)) {-# INLINE toPixelYA #-} -- ToRGB -- | Conversion to `RGB` color space. class ColorSpace cs e => ToRGB cs e where -- | Convert to an `RGB` pixel. toPixelRGB :: Pixel cs e -> Pixel RGB Double instance ToRGB X Bit where toPixelRGB (PixelX b) = pure $ eToDouble b {-# INLINE toPixelRGB #-} instance Elevator e => ToRGB Y e where toPixelRGB (PixelY g) = pure $ eToDouble g {-# INLINE toPixelRGB #-} instance Elevator e => ToRGB YA e where toPixelRGB = toPixelRGB . dropAlpha {-# INLINE toPixelRGB #-} instance Elevator e => ToRGB RGB e where toPixelRGB = toDouble {-# INLINE toPixelRGB #-} instance Elevator e => ToRGB RGBA e where toPixelRGB = toDouble . dropAlpha {-# INLINE toPixelRGB #-} instance Elevator e => ToRGB HSI e where toPixelRGB (toDouble -> PixelHSI h' s i) = getRGB (h'*2*pi) where !is = i*s !second = i - is errorHue = error $ "HSI pixel is not properly scaled, Hue: " ++ show h' getFirst !a !b = i + is*cos a/cos b {-# INLINE getFirst #-} getThird !v1 !v2 = i + 2*is + v1 - v2 {-# INLINE getThird #-} getRGB h | h < 0 = errorHue | h < 2*pi/3 = let !r = getFirst h (pi/3 - h) !b = second !g = getThird b r in PixelRGB r g b | h < 4*pi/3 = let !g = getFirst (h - 2*pi/3) (h + pi) !r = second !b = getThird r g in PixelRGB r g b | h < 2*pi = let !b = getFirst (h - 4*pi/3) (2*pi - pi/3 - h) !g = second !r = getThird g b in PixelRGB r g b | otherwise = errorHue {-# INLINE getRGB #-} {-# INLINE toPixelRGB #-} instance Elevator e => ToRGB HSIA e where toPixelRGB = toPixelRGB . dropAlpha {-# INLINE toPixelRGB #-} instance Elevator e => ToRGB YCbCr e where toPixelRGB (toDouble -> PixelYCbCr y cb cr) = PixelRGB r g b where !r = clamp01 (y + 1.402*(cr - 0.5)) !g = clamp01 (y - 0.34414*(cb - 0.5) - 0.71414*(cr - 0.5)) !b = clamp01 (y + 1.772*(cb - 0.5)) {-# INLINE toPixelRGB #-} instance Elevator e => ToRGB YCbCrA e where toPixelRGB = toPixelRGB . dropAlpha {-# INLINE toPixelRGB #-} instance Elevator e => ToRGB CMYK e where toPixelRGB (toDouble -> PixelCMYK c m y k) = PixelRGB r g b where !r = (1-c)*(1-k) !g = (1-m)*(1-k) !b = (1-y)*(1-k) {-# INLINE toPixelRGB #-} instance Elevator e => ToRGB CMYKA e where toPixelRGB = toPixelRGB . dropAlpha {-# INLINE toPixelRGB #-} -- ToRGBA -- | Conversion to `RGBA` from another color space with Alpha channel. class ToRGB cs e => ToRGBA cs e where -- | Convert to an `RGBA` pixel. toPixelRGBA :: Pixel cs e -> Pixel RGBA Double toPixelRGBA = addAlpha 1 . toPixelRGB {-# INLINE toPixelRGBA #-} instance ToRGBA X Bit instance ToRGB Y e => ToRGBA Y e instance Elevator e => ToRGBA YA e where toPixelRGBA !px = addAlpha (eToDouble $ getAlpha px) (toPixelRGB (dropAlpha px)) {-# INLINE toPixelRGBA #-} instance ToRGB RGB e => ToRGBA RGB e instance Elevator e => ToRGBA RGBA e where toPixelRGBA = toDouble {-# INLINE toPixelRGBA #-} instance ToRGB HSI e => ToRGBA HSI e instance Elevator e => ToRGBA HSIA e where toPixelRGBA !px = addAlpha (eToDouble $ getAlpha px) (toPixelRGB (dropAlpha px)) {-# INLINE toPixelRGBA #-} instance ToRGB CMYK e => ToRGBA CMYK e instance Elevator e => ToRGBA CMYKA e where toPixelRGBA !px = addAlpha (eToDouble $ getAlpha px) (toPixelRGB (dropAlpha px)) {-# INLINE toPixelRGBA #-} instance ToRGB YCbCr e => ToRGBA YCbCr e instance Elevator e => ToRGBA YCbCrA e where toPixelRGBA !px = addAlpha (eToDouble $ getAlpha px) (toPixelRGB (dropAlpha px)) {-# INLINE toPixelRGBA #-} -- ToHSI -- | Conversion to `HSI` color space. class ColorSpace cs e => ToHSI cs e where -- | Convert to an `HSI` pixel. toPixelHSI :: Pixel cs e -> Pixel HSI Double instance Elevator e => ToHSI Y e where toPixelHSI (PixelY y) = PixelHSI 0 0 $ eToDouble y {-# INLINE toPixelHSI #-} instance Elevator e => ToHSI YA e where toPixelHSI = toPixelHSI . dropAlpha {-# INLINE toPixelHSI #-} instance Elevator e => ToHSI RGB e where toPixelHSI (toDouble -> PixelRGB r g b) = PixelHSI h s i where !h' = atan2 y x !h = (if h' < 0 then h' + 2*pi else h') / (2*pi) !s = if i == 0 then 0 else 1 - minimum [r, g, b] / i !i = (r + g + b) / 3 !x = (2*r - g - b) / 2.449489742783178 !y = (g - b) / 1.4142135623730951 {-# INLINE toPixelHSI #-} instance Elevator e => ToHSI RGBA e where toPixelHSI = toPixelHSI . dropAlpha {-# INLINE toPixelHSI #-} instance Elevator e => ToHSI HSI e where toPixelHSI = toDouble {-# INLINE toPixelHSI #-} instance Elevator e => ToHSI HSIA e where toPixelHSI = toPixelHSI . dropAlpha {-# INLINE toPixelHSI #-} instance Elevator e => ToHSI YCbCr e where toPixelHSI = toPixelHSI . toPixelRGB {-# INLINE toPixelHSI #-} instance Elevator e => ToHSI YCbCrA e where toPixelHSI = toPixelHSI . dropAlpha {-# INLINE toPixelHSI #-} instance Elevator e => ToHSI CMYK e where toPixelHSI = toPixelHSI . toPixelRGB {-# INLINE toPixelHSI #-} instance Elevator e => ToHSI CMYKA e where toPixelHSI = toPixelHSI . dropAlpha {-# INLINE toPixelHSI #-} -- ToHSIA -- | Conversion to `HSIA` from another color space with Alpha channel. class ToHSI cs e => ToHSIA cs e where -- | Convert to an `HSIA` pixel. toPixelHSIA :: Pixel cs e -> Pixel HSIA Double toPixelHSIA = addAlpha 1 . toPixelHSI {-# INLINE toPixelHSIA #-} instance ToHSI Y e => ToHSIA Y e instance Elevator e => ToHSIA YA e where toPixelHSIA !px = addAlpha (eToDouble $ getAlpha px) (toPixelHSI (dropAlpha px)) {-# INLINE toPixelHSIA #-} instance ToHSI RGB e => ToHSIA RGB e instance Elevator e => ToHSIA RGBA e where toPixelHSIA !px = addAlpha (eToDouble $ getAlpha px) (toPixelHSI (dropAlpha px)) {-# INLINE toPixelHSIA #-} instance ToHSI HSI e => ToHSIA HSI e instance Elevator e => ToHSIA HSIA e where toPixelHSIA = toDouble {-# INLINE toPixelHSIA #-} instance ToHSI CMYK e => ToHSIA CMYK e instance Elevator e => ToHSIA CMYKA e where toPixelHSIA !px = addAlpha (eToDouble $ getAlpha px) (toPixelHSI (dropAlpha px)) {-# INLINE toPixelHSIA #-} instance ToHSI YCbCr e => ToHSIA YCbCr e instance Elevator e => ToHSIA YCbCrA e where toPixelHSIA !px = addAlpha (eToDouble $ getAlpha px) (toPixelHSI (dropAlpha px)) {-# INLINE toPixelHSIA #-} -- ToCMYK -- | Conversion to `CMYK` color space. class ColorSpace cs e => ToCMYK cs e where -- | Convert to a `CMYK` pixel. toPixelCMYK :: Pixel cs e -> Pixel CMYK Double instance Elevator e => ToCMYK Y e where toPixelCMYK = toPixelCMYK . toPixelRGB {-# INLINE toPixelCMYK #-} instance Elevator e => ToCMYK YA e where toPixelCMYK = toPixelCMYK . dropAlpha {-# INLINE toPixelCMYK #-} instance Elevator e => ToCMYK RGB e where toPixelCMYK (toDouble -> PixelRGB r g b) = PixelCMYK c m y k where !c = (1 - r - k)/(1 - k) !m = (1 - g - k)/(1 - k) !y = (1 - b - k)/(1 - k) !k = 1 - max r (max g b) {-# INLINE toPixelCMYK #-} instance Elevator e => ToCMYK RGBA e where toPixelCMYK = toPixelCMYK . dropAlpha {-# INLINE toPixelCMYK #-} instance Elevator e => ToCMYK HSI e where toPixelCMYK = toPixelCMYK . toPixelRGB {-# INLINE toPixelCMYK #-} instance Elevator e => ToCMYK HSIA e where toPixelCMYK = toPixelCMYK . dropAlpha {-# INLINE toPixelCMYK #-} instance Elevator e => ToCMYK CMYK e where toPixelCMYK = toDouble {-# INLINE toPixelCMYK #-} instance Elevator e => ToCMYK CMYKA e where toPixelCMYK = toPixelCMYK . dropAlpha {-# INLINE toPixelCMYK #-} instance Elevator e => ToCMYK YCbCr e where toPixelCMYK = toPixelCMYK . toPixelRGB {-# INLINE toPixelCMYK #-} instance Elevator e => ToCMYK YCbCrA e where toPixelCMYK = toPixelCMYK . dropAlpha {-# INLINE toPixelCMYK #-} -- ToCMYKA -- | Conversion to `CMYKA`. class ToCMYK cs e => ToCMYKA cs e where -- | Convert to a `CMYKA` pixel. toPixelCMYKA :: Pixel cs e -> Pixel CMYKA Double toPixelCMYKA = addAlpha 1 . toPixelCMYK {-# INLINE toPixelCMYKA #-} instance ToCMYK Y e => ToCMYKA Y e instance Elevator e => ToCMYKA YA e where toPixelCMYKA !px = addAlpha (eToDouble $ getAlpha px) (toPixelCMYK (dropAlpha px)) {-# INLINE toPixelCMYKA #-} instance ToCMYK RGB e => ToCMYKA RGB e instance Elevator e => ToCMYKA RGBA e where toPixelCMYKA !px = addAlpha (eToDouble $ getAlpha px) (toPixelCMYK (dropAlpha px)) {-# INLINE toPixelCMYKA #-} instance ToCMYK HSI e => ToCMYKA HSI e instance Elevator e => ToCMYKA HSIA e where toPixelCMYKA !px = addAlpha (eToDouble $ getAlpha px) (toPixelCMYK (dropAlpha px)) {-# INLINE toPixelCMYKA #-} instance ToCMYK CMYK e => ToCMYKA CMYK e instance Elevator e => ToCMYKA CMYKA e where toPixelCMYKA = toDouble {-# INLINE toPixelCMYKA #-} instance ToCMYK YCbCr e => ToCMYKA YCbCr e instance Elevator e => ToCMYKA YCbCrA e where toPixelCMYKA !px = addAlpha (eToDouble $ getAlpha px) (toPixelCMYK (dropAlpha px)) {-# INLINE toPixelCMYKA #-} -- ToYCbCr -- | Conversion to `YCbCr` color space. class ColorSpace cs e => ToYCbCr cs e where -- | Convert to an `YCbCr` pixel. toPixelYCbCr :: Pixel cs e -> Pixel YCbCr Double instance Elevator e => ToYCbCr Y e where toPixelYCbCr = toPixelYCbCr . toPixelRGB {-# INLINE toPixelYCbCr #-} instance Elevator e => ToYCbCr YA e where toPixelYCbCr = toPixelYCbCr . dropAlpha {-# INLINE toPixelYCbCr #-} instance Elevator e => ToYCbCr RGB e where toPixelYCbCr (toDouble -> PixelRGB r g b) = PixelYCbCr y cb cr where !y = clamp01 ( 0.299*r + 0.587*g + 0.114*b) !cb = clamp01 (0.5 - 0.168736*r - 0.331264*g + 0.5*b) !cr = clamp01 (0.5 + 0.5*r - 0.418688*g - 0.081312*b) {-# INLINE toPixelYCbCr #-} instance Elevator e => ToYCbCr RGBA e where toPixelYCbCr = toPixelYCbCr . dropAlpha {-# INLINE toPixelYCbCr #-} instance Elevator e => ToYCbCr HSI e where toPixelYCbCr = toPixelYCbCr . toPixelRGB {-# INLINE toPixelYCbCr #-} instance Elevator e => ToYCbCr HSIA e where toPixelYCbCr = toPixelYCbCr . dropAlpha {-# INLINE toPixelYCbCr #-} instance Elevator e => ToYCbCr YCbCr e where toPixelYCbCr = toDouble {-# INLINE toPixelYCbCr #-} instance Elevator e => ToYCbCr YCbCrA e where toPixelYCbCr = toPixelYCbCr . dropAlpha {-# INLINE toPixelYCbCr #-} instance Elevator e => ToYCbCr CMYK e where toPixelYCbCr = toPixelYCbCr . toPixelRGB {-# INLINE toPixelYCbCr #-} instance Elevator e => ToYCbCr CMYKA e where toPixelYCbCr = toPixelYCbCr . dropAlpha {-# INLINE toPixelYCbCr #-} -- ToYCbCrA -- | Conversion to `YCbCrA` from another color space with Alpha channel. class ToYCbCr cs e => ToYCbCrA cs e where -- | Convert to an `YCbCrA` pixel. toPixelYCbCrA :: Pixel cs e -> Pixel YCbCrA Double toPixelYCbCrA = addAlpha 1 . toPixelYCbCr {-# INLINE toPixelYCbCrA #-} instance ToYCbCr Y e => ToYCbCrA Y e instance Elevator e => ToYCbCrA YA e where toPixelYCbCrA !px = addAlpha (eToDouble $ getAlpha px) (toPixelYCbCr (dropAlpha px)) {-# INLINE toPixelYCbCrA #-} instance ToYCbCr RGB e => ToYCbCrA RGB e instance ToYCbCr HSI e => ToYCbCrA HSI e instance Elevator e => ToYCbCrA HSIA e where toPixelYCbCrA !px = addAlpha (eToDouble $ getAlpha px) (toPixelYCbCr (dropAlpha px)) {-# INLINE toPixelYCbCrA #-} instance Elevator e => ToYCbCrA RGBA e where toPixelYCbCrA !px = addAlpha (eToDouble $ getAlpha px) (toPixelYCbCr (dropAlpha px)) {-# INLINE toPixelYCbCrA #-} instance ToYCbCr CMYK e => ToYCbCrA CMYK e instance Elevator e => ToYCbCrA CMYKA e where toPixelYCbCrA !px = addAlpha (eToDouble $ getAlpha px) (toPixelYCbCr (dropAlpha px)) {-# INLINE toPixelYCbCrA #-} instance ToYCbCr YCbCr e => ToYCbCrA YCbCr e instance Elevator e => ToYCbCrA YCbCrA e where toPixelYCbCrA = toDouble {-# INLINE toPixelYCbCrA #-} -- | Change pixel precision to `Word8`. toWord8 :: (Functor (Pixel cs), Elevator e) => Pixel cs e -> Pixel cs Word8 toWord8 = fmap eToWord8 {-# INLINABLE toWord8 #-} -- | Change pixel precision to `Word16`. toWord16 :: (Functor (Pixel cs), Elevator e) => Pixel cs e -> Pixel cs Word16 toWord16 = fmap eToWord16 {-# INLINABLE toWord16 #-} -- | Change pixel precision to `Word32`. toWord32 :: (Functor (Pixel cs), Elevator e) => Pixel cs e -> Pixel cs Word32 toWord32 = fmap eToWord32 {-# INLINABLE toWord32 #-} -- | Change pixel precision to `Word64`. toWord64 :: (Functor (Pixel cs), Elevator e) => Pixel cs e -> Pixel cs Word64 toWord64 = fmap eToWord64 {-# INLINABLE toWord64 #-} -- | Change pixel precision to `Float`. toFloat :: (Functor (Pixel cs), Elevator e) => Pixel cs e -> Pixel cs Float toFloat = fmap eToFloat {-# INLINABLE toFloat #-} -- | Change pixel precision to `Double`. toDouble :: (Functor (Pixel cs), Elevator e) => Pixel cs e -> Pixel cs Double toDouble = fmap eToDouble {-# INLINABLE toDouble #-} -- | Change pixel precision from `Double`. fromDouble :: (Functor (Pixel cs), Elevator e) => Pixel cs Double -> Pixel cs e fromDouble = fmap eFromDouble {-# INLINABLE fromDouble #-}