sdl2-gfx-0.3.0.0: src/SDL/ImageFilter.hs
-- |
--
-- Module : SDL.ImageFilter
-- Copyright : (c) 2015 Siniša Biđin
-- License : MIT
-- Maintainer : sinisa@bidin.eu
-- Stability : experimental
--
-- Bindings to @SDL2_gfx@'s MMX image filter functionality.
module SDL.ImageFilter
( -- * Query MMX
usingMMX,
disableMMX,
enableMMX,
-- * Vector operations
add,
mean,
sub,
absDiff,
mult,
multNor,
multDivBy2,
multDivBy4,
bitAnd,
bitOr,
div,
bitNegation,
addByte,
addUInt,
addByteToHalf,
subByte,
subUInt,
shiftRight,
shiftRightUInt,
multByByte,
shiftRightAndMultByByte,
shiftLeftByte,
shiftLeftUInt,
shiftLeft,
binarizeUsingThreshold,
clipToRange,
normalizeLinear,
)
where
import Control.Monad.IO.Class (MonadIO, liftIO)
import Data.Vector.Storable (Vector)
import qualified Data.Vector.Storable as V
import Data.Word (Word8)
import Foreign.C.Types (CInt, CUChar, CUInt)
import Foreign.ForeignPtr (newForeignPtr)
import Foreign.Marshal.Alloc (finalizerFree, mallocBytes)
import Foreign.Ptr (Ptr, castPtr)
import qualified SDL.Raw.ImageFilter
import System.IO.Unsafe (unsafePerformIO)
import Prelude hiding (div)
-- | Are we using MMX code?
usingMMX :: MonadIO m => m Bool
usingMMX = (== 1) <$> SDL.Raw.ImageFilter.mmxDetect
-- | Disable MMX, use non-MMX code instead.
disableMMX :: MonadIO m => m ()
disableMMX = liftIO SDL.Raw.ImageFilter.mmxOff
-- | Use MMX code if available.
enableMMX :: MonadIO m => m ()
enableMMX = liftIO SDL.Raw.ImageFilter.mmxOn
{-# INLINE minLen #-}
minLen :: Integral a => Vector Word8 -> Vector Word8 -> a
minLen x = fromIntegral . min (V.length x) . V.length
mallocVector :: Int -> (Ptr CUChar -> IO a) -> IO (Vector Word8)
mallocVector len act = do
p <- mallocBytes len
_ <- act p -- TODO: Check for errors?
f <- newForeignPtr finalizerFree $ castPtr p
return $ V.unsafeFromForeignPtr0 f len
binary ::
(Ptr CUChar -> Ptr CUChar -> Ptr CUChar -> CUInt -> IO CInt) ->
(Vector Word8 -> Vector Word8 -> Vector Word8)
binary f x y =
unsafePerformIO
. V.unsafeWith x
$ \x' ->
V.unsafeWith y $ \y' ->
mallocVector (minLen x y) $ \z' ->
f (castPtr x') (castPtr y') z' (minLen x y)
add :: Vector Word8 -> Vector Word8 -> Vector Word8
add = binary SDL.Raw.ImageFilter.add
mean :: Vector Word8 -> Vector Word8 -> Vector Word8
mean = binary SDL.Raw.ImageFilter.mean
sub :: Vector Word8 -> Vector Word8 -> Vector Word8
sub = binary SDL.Raw.ImageFilter.sub
absDiff :: Vector Word8 -> Vector Word8 -> Vector Word8
absDiff = binary SDL.Raw.ImageFilter.absDiff
mult :: Vector Word8 -> Vector Word8 -> Vector Word8
mult = binary SDL.Raw.ImageFilter.mult
multNor :: Vector Word8 -> Vector Word8 -> Vector Word8
multNor = binary SDL.Raw.ImageFilter.multNor
multDivBy2 :: Vector Word8 -> Vector Word8 -> Vector Word8
multDivBy2 = binary SDL.Raw.ImageFilter.multDivBy2
multDivBy4 :: Vector Word8 -> Vector Word8 -> Vector Word8
multDivBy4 = binary SDL.Raw.ImageFilter.multDivBy4
bitAnd :: Vector Word8 -> Vector Word8 -> Vector Word8
bitAnd = binary SDL.Raw.ImageFilter.bitAnd
bitOr :: Vector Word8 -> Vector Word8 -> Vector Word8
bitOr = binary SDL.Raw.ImageFilter.bitOr
div :: Vector Word8 -> Vector Word8 -> Vector Word8
div = binary SDL.Raw.ImageFilter.div
{-# INLINE cuchar #-}
cuchar :: Word8 -> CUChar
cuchar = fromIntegral
bitNegation :: Vector Word8 -> Vector Word8
bitNegation x =
unsafePerformIO
. V.unsafeWith x
$ \x' ->
mallocVector (V.length x) $ \y' ->
SDL.Raw.ImageFilter.bitNegation
(castPtr x')
y'
(fromIntegral $ V.length x)
binaryByte ::
(Ptr CUChar -> Ptr CUChar -> CUInt -> CUChar -> IO CInt) ->
(Word8 -> Vector Word8 -> Vector Word8)
binaryByte f b x =
unsafePerformIO
. V.unsafeWith x
$ \x' ->
mallocVector (V.length x) $ \y' ->
f (castPtr x') y' (fromIntegral $ V.length x) (cuchar b)
addByte :: Word8 -> Vector Word8 -> Vector Word8
addByte = binaryByte SDL.Raw.ImageFilter.addByte
addByteToHalf :: Word8 -> Vector Word8 -> Vector Word8
addByteToHalf = binaryByte SDL.Raw.ImageFilter.addByteToHalf
subByte :: Word8 -> Vector Word8 -> Vector Word8
subByte = binaryByte SDL.Raw.ImageFilter.subByte
shiftRight :: Word8 -> Vector Word8 -> Vector Word8
shiftRight = binaryByte SDL.Raw.ImageFilter.shiftRight
multByByte :: Word8 -> Vector Word8 -> Vector Word8
multByByte = binaryByte SDL.Raw.ImageFilter.multByByte
shiftLeftByte :: Word8 -> Vector Word8 -> Vector Word8
shiftLeftByte = binaryByte SDL.Raw.ImageFilter.shiftLeftByte
shiftRightUInt :: Word8 -> Vector Word8 -> Vector Word8
shiftRightUInt = binaryByte SDL.Raw.ImageFilter.shiftRightUInt
shiftLeftUInt :: Word8 -> Vector Word8 -> Vector Word8
shiftLeftUInt = binaryByte SDL.Raw.ImageFilter.shiftLeftUInt
shiftLeft :: Word8 -> Vector Word8 -> Vector Word8
shiftLeft = binaryByte SDL.Raw.ImageFilter.shiftLeft
binarizeUsingThreshold :: Word8 -> Vector Word8 -> Vector Word8
binarizeUsingThreshold = binaryByte SDL.Raw.ImageFilter.binarizeUsingThreshold
binaryUInt ::
(Ptr CUChar -> Ptr CUChar -> CUInt -> CUInt -> IO CInt) ->
(CUInt -> Vector Word8 -> Vector Word8)
binaryUInt f i x =
unsafePerformIO
. V.unsafeWith x
$ \x' ->
mallocVector (V.length x) $ \y' ->
f (castPtr x') y' (fromIntegral $ V.length x) i
addUInt :: CUInt -> Vector Word8 -> Vector Word8
addUInt = binaryUInt SDL.Raw.ImageFilter.addUInt
subUInt :: CUInt -> Vector Word8 -> Vector Word8
subUInt = binaryUInt SDL.Raw.ImageFilter.subUInt
shiftRightAndMultByByte :: Word8 -> Word8 -> Vector Word8 -> Vector Word8
shiftRightAndMultByByte s m x =
unsafePerformIO
. V.unsafeWith x
$ \x' ->
mallocVector (V.length x) $ \y' ->
SDL.Raw.ImageFilter.shiftRightAndMultByByte
(castPtr x')
y'
(fromIntegral $ V.length x)
(cuchar s)
(cuchar m)
clipToRange :: Word8 -> Word8 -> Vector Word8 -> Vector Word8
clipToRange a b x =
unsafePerformIO
. V.unsafeWith x
$ \x' ->
mallocVector (V.length x) $ \y' ->
SDL.Raw.ImageFilter.clipToRange
(castPtr x')
y'
(fromIntegral $ V.length x)
(cuchar a)
(cuchar b)
normalizeLinear :: CInt -> CInt -> CInt -> CInt -> Vector Word8 -> Vector Word8
normalizeLinear cmin cmax nmin nmax x =
unsafePerformIO
. V.unsafeWith x
$ \x' ->
mallocVector (V.length x) $ \y' ->
SDL.Raw.ImageFilter.normalizeLinear
(castPtr x')
y'
(fromIntegral $ V.length x)
cmin
cmax
nmin
nmax