worldturtle-0.2.2.0: Graphics/WorldTurtle/Color.hs
{-|
Module : Graphics.WorldTurtle.Color
Description : Color functions
Copyright : (c) Archibald Neil MacDonald, 2020
License : BSD3
Maintainer : archibaldnmac@gmail.com
Stability : experimental
Portability : POSIX
This module is a collection of color manipulation commands!
-}
module Graphics.WorldTurtle.Color
( module Graphics.Gloss.Data.Color
, shiftHue
) where
import Data.Matrix
import Graphics.Gloss.Data.Color
import Graphics.WorldTurtle.Internal.Coords (degToRad)
-- | Rotates a given color's hue between [0, 360) degrees.
shiftHue :: Float -- ^ Degrees to change hue.
-> Color -- ^ Color to shift.
-> Color -- ^ Resultant color with hue shifted.
shiftHue d c = let d' = degToRad d -- Radians to degrees
hMatrix = hueMatrix d'
(r, g, b, a) = rgbaOfColor c
cMatrix = fromList 1 3 [r, g, b]
cMatrix' = cMatrix * hMatrix
[r', g', b'] = toList cMatrix'
in makeColor r' g' b' a
-- Haskell form of solution posted here:
-- https://stackoverflow.com/questions/8507885/shift-hue-of-an-rgb-color
hueMatrix :: Float -> Matrix Float
hueMatrix degrees = matrix 3 3 (`calcForIndex` degrees)
calcForIndex :: (Int, Int) -> Float -> Float
calcForIndex (1, 1) = diag_
calcForIndex (1, 2) = perm1_
calcForIndex (1, 3) = perm2_
calcForIndex (2, 1) = perm2_
calcForIndex (2, 2) = diag_
calcForIndex (2, 3) = perm1_
calcForIndex (3, 1) = perm1_
calcForIndex (3, 2) = perm2_
calcForIndex (3, 3) = diag_
calcForIndex _ = error "We only work with 3x3 matrices!"
diag_ :: Float -> Float
diag_ d = cos d + 1/3 * (1.0 - cos d)
perm1_ :: Float -> Float
perm1_ d = 1/3 * (1 - cos d) - sqrt (1/3) * sin d
perm2_ :: Float -> Float
perm2_ d = 1/3 * (1 - cos d) + sqrt (1/3) * sin d