module GEGL.Buffer.BufferIterator
( FFI.GeglBufferIterator(..)
, gegl_buffer_iterator_new
, gegl_buffer_iterator_next
, Pixel(..)
, FFI.ComponentValue(..)
, pixelMap
, pixelPoke
) where
import qualified GEGL.FFI.Buffer.BufferIterator as FFI
import GEGL.FFI.Buffer (GeglBuffer(..))
import GEGL.FFI.Rectangle
import GEGL.Enums
import GEGL.Color
import qualified BABL.Format as BF
import BABL.FFI.Format (BablFormatPtr(..))
import Foreign.Marshal.Utils (new)
import Foreign.Ptr
import Foreign.C.Types
import Foreign.Storable (peek, poke)
import Data.List.Split
import Data.Maybe (fromMaybe)
import Control.Monad.Loops (whileM_)
import Debug.Trace
data Pixel = Pixel
{ pixelX :: Int
, pixelY :: Int
, pixelData ::
( FFI.ComponentValue
, FFI.ComponentValue
, FFI.ComponentValue
, FFI.ComponentValue
)
}
gegl_buffer_iterator_new
:: GeglBuffer
-> GeglRectangle
-> BF.PixelFormat
-> GeglAccessMode
-> GeglAbyssPolicy
-> IO FFI.GeglBufferIterator
gegl_buffer_iterator_new (GeglBuffer buf) roi format am ap = do
roiPtr <- new roi
(BablFormatPtr formatPtr) <- BF.babl_format format
FFI.GeglBufferIterator <$> FFI.c_gegl_buffer_iterator_new
buf
roiPtr
(CInt 0)
formatPtr
(marshal am)
(marshal ap)
gegl_buffer_iterator_next
:: FFI.GeglBufferIterator
-> IO Bool
gegl_buffer_iterator_next (FFI.GeglBufferIterator ptr) =
FFI.c_gegl_buffer_iterator_next ptr
marshal :: Enum e => e -> CInt
marshal = CInt . fromIntegral . fromEnum
pixelPoke
:: GeglBuffer
-> GeglRectangle
-> BF.PixelFormat
-> GeglAccessMode
-> GeglAbyssPolicy
-> ((Int, Int) -> Pixel)
-> IO ()
pixelPoke buf rect form am ap func = do
(FFI.GeglBufferIterator iterPtr) <- gegl_buffer_iterator_new buf rect form am ap
whileM_ (gegl_buffer_iterator_next (FFI.GeglBufferIterator iterPtr))
(do
roi <- FFI.c_gegl_peek_roi iterPtr
let idx = [1..(rectangleWidth roi * rectangleHeight roi)]
!newList = concatMap (pToC $ BF.babl_components_per_pixel form) $ map func $ map (flip iToCoord roi) idx
FFI.c_gegl_poke_data iterPtr newList form
)
pixelMap
:: GeglBuffer
-> GeglRectangle
-> BF.PixelFormat
-> GeglAccessMode
-> GeglAbyssPolicy
-> (Pixel -> Pixel)
-> IO ()
pixelMap buf rect form am ap func = do
(FFI.GeglBufferIterator iterPtr) <- gegl_buffer_iterator_new buf rect form am ap
whileM_ (gegl_buffer_iterator_next (FFI.GeglBufferIterator iterPtr))
(do
values <- FFI.c_gegl_peek_data iterPtr form
roi <- FFI.c_gegl_peek_roi iterPtr
let newList = mapPixel values form roi func
FFI.c_gegl_poke_data iterPtr newList form
)
mapPixel
:: [FFI.ComponentValue]
-> BF.PixelFormat
-> GeglRectangle
-> (Pixel -> Pixel)
-> [FFI.ComponentValue]
mapPixel input format rect@GeglRectangle{..} funct =
concatMap (pToC cpp) $ map funct $ map (cToP rect cpp) chunks
where
!cpp = BF.babl_components_per_pixel format
chunks = zip [0..] $ chunksOf cpp input
iToCoord i GeglRectangle{..} =
( (rectangleX + ((i 1) `mod` (rectangleWidth)))
, (rectangleY + ((i 1) `div` (rectangleWidth)))
)
cToP rect cpp (i, pd) = Pixel (fst tup) (snd tup) $ toPixel cpp pd
where
tup = (iToCoord i rect)
pToC cpp (Pixel _ _ col) = toList cpp col
toPixel
:: Int
-> [FFI.ComponentValue]
-> (FFI.ComponentValue, FFI.ComponentValue, FFI.ComponentValue, FFI.ComponentValue)
toPixel cpp d = case cpp of
1 -> (head d, nullc , nullc , nullc)
2 -> (head d, d !! 1, nullc , nullc)
3 -> (head d, d !! 1, d !! 2, nullc)
4 -> (head d, d !! 1, d !! 2, d !! 3)
where
!nullc = FFI.CVu32 0
toList
:: Int
-> (FFI.ComponentValue, FFI.ComponentValue, FFI.ComponentValue, FFI.ComponentValue)
-> [FFI.ComponentValue]
toList cpp (a, b ,c ,d) =
case cpp of
1 -> [a]
2 -> [a, b]
3 -> [a, b, c]
4 -> [a, b, c, d]