{-# LANGUAGE BangPatterns #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE TypeFamilies #-} -- | -- Module : Graphics.Image.ColorSpace.Luma -- Copyright : (c) Alexey Kuleshevich 2016 -- License : BSD3 -- Maintainer : Alexey Kuleshevich -- Stability : experimental -- Portability : non-portable -- module Graphics.Image.ColorSpace.Luma ( Y(..), YA(..), Pixel(..), ToY(..), ToYA(..) ) where import Prelude hiding (map) import Graphics.Image.Interface import Data.Typeable (Typeable) import qualified Data.Monoid as M (mappend, mempty) import qualified Data.Colour as C import qualified Data.Colour.Names as C -- | Luma or brightness, that is usually denoted as @Y'@. data Y = Y deriving (Eq, Enum, Typeable) -- | Luma with Alpha channel. data YA = YA -- ^ Luma | AlphaYA -- ^ Alpha channel deriving (Eq, Enum, Typeable) -- | Conversion to Luma color space. class ColorSpace cs => ToY cs where -- | Convert a pixel to Luma pixel. toPixelY :: Pixel cs Double -> Pixel Y Double -- | Convert an image to Luma image. toImageY :: (Array arr cs Double, Array arr Y Double) => Image arr cs Double -> Image arr Y Double toImageY = map toPixelY {-# INLINE toImageY #-} -- | Conversion to Luma from another color space with Alpha channel. class (ToY (Opaque cs), Alpha cs) => ToYA cs where -- | Convert a pixel to Luma pixel with Alpha. toPixelYA :: Pixel cs Double -> Pixel YA Double toPixelYA px = addAlpha (getAlpha px) (toPixelY (dropAlpha px)) {-# INLINE toPixelYA #-} -- | Convert an image to Luma image with Alpha. toImageYA :: (Array arr cs Double, Array arr YA Double) => Image arr cs Double -> Image arr YA Double toImageYA = map toPixelYA {-# INLINE toImageYA #-} instance ColorSpace Y where type PixelElt Y e = e data Pixel Y e = PixelY !e deriving (Ord, Eq) fromChannel = PixelY {-# INLINE fromChannel #-} fromElt = PixelY {-# INLINE fromElt #-} toElt (PixelY y) = y {-# INLINE toElt #-} getPxCh (PixelY y) _ = y {-# INLINE getPxCh #-} chOp !f (PixelY y) = PixelY (f Y y) {-# INLINE chOp #-} pxOp !f (PixelY y) = PixelY (f y) {-# INLINE pxOp #-} chApp (PixelY fy) (PixelY y) = PixelY (fy y) {-# INLINE chApp #-} pxFoldMap f (PixelY y) = f y `M.mappend` M.mempty {-# INLINE pxFoldMap #-} csColour _ = C.opaque C.darkgray instance ColorSpace YA where type PixelElt YA e = (e, e) data Pixel YA e = PixelYA !e !e deriving Eq fromChannel !e = PixelYA e e {-# INLINE fromChannel #-} fromElt !(g, a) = PixelYA g a {-# INLINE fromElt #-} toElt (PixelYA g a) = (g, a) {-# INLINE toElt #-} getPxCh (PixelYA g _) YA = g getPxCh (PixelYA _ a) AlphaYA = a {-# INLINE getPxCh #-} chOp !f (PixelYA g a) = PixelYA (f YA g) (f AlphaYA a) {-# INLINE chOp #-} pxOp !f (PixelYA g a) = PixelYA (f g) (f a) {-# INLINE pxOp #-} chApp (PixelYA fy fa) (PixelYA y a) = PixelYA (fy y) (fa a) {-# INLINE chApp #-} pxFoldMap f (PixelYA y a) = f y `M.mappend` f a {-# INLINE pxFoldMap #-} csColour AlphaYA = C.opaque C.gray csColour ch = csColour $ opaque ch instance Alpha YA where type Opaque YA = Y getAlpha (PixelYA _ a) = a {-# INLINE getAlpha #-} addAlpha !a (PixelY g) = PixelYA g a {-# INLINE addAlpha #-} dropAlpha (PixelYA g _) = PixelY g {-# INLINE dropAlpha #-} opaque YA = Y opaque _ = error "Data.Image.ColorSpace.Luma (Alpha.opaque)" instance Show Y where show Y = "Luma" instance Show YA where show AlphaYA = "Alpha" show ch = show $ opaque ch instance Show e => Show (Pixel Y e) where show (PixelY g) = "" instance Show e => Show (Pixel YA e) where show (PixelYA g a) = "" instance Monad (Pixel Y) where return = PixelY {-# INLINE return #-} (>>=) (PixelY y) f = f y {-# INLINE (>>=) #-}