-- | Conversion to raster forms. -- -- TODO: the reverse. module Propane.Raster ( rasterize , rastimate ) where import qualified Data.Sequence as S import qualified Data.Colour as C import qualified Data.Colour.SRGB as C import qualified Data.Array.Repa as R import Data.Array.Repa ( Z(..), (:.)(..) ) import Propane.Types import Propane.Transform ( spaced ) type W8888 = (Word8, Word8, Word8, Word8) -- | Convert the @'Image'@ region [-1, 1] x [-1, 1] to a @'Raster'@ with -- the specified number of pixels. rasterize :: Size -> Image Colour -> Raster rasterize (Size w h) im = Raster . chans $ R.fromFunction dim f where f = quant . im . point dw = fromIntegral w - 1 dh = fromIntegral h - 1 dim = Z :. w :. h point :: R.DIM2 -> R2 point (Z :. y :. x) = (adj dw x, adj dh y) where adj d n = (2 * fromIntegral n / d) - 1 quant :: Colour -> W8888 quant c = (r, g, b, a) where C.RGB r g b = C.toSRGB24 (c `C.over` C.black) a = round (C.alphaChannel c * 255.0) chans :: R.Array R.DIM2 W8888 -> R.Array R.DIM3 Word8 chans arr = R.traverse arr (:. 4) chan where chan a (Z :. y :. x :. c) = ix c (a (Z :. y :. x)) ix 0 (r,_,_,_) = r ix 1 (_,g,_,_) = g ix 2 (_,_,b,_) = b ix 3 (_,_,_,a) = a ix _ _ = error "Propane.Quantize: internal error (bad ix)" -- | Convert the animation, for times in [0,1), to a @'Rastimation'@ with -- the specified numbers of frames and pixels. rastimate :: Count -> Size -> Animation Colour -> Rastimation rastimate n sz ani = Rastimation (S.fromList frames) where frames = map (rasterize sz . ani) (spaced n 0 1)