--------------------------------------------------------------------------------
-- Module      : Data.Bitmap.Simple
-- Version     : 0.0.2
-- License     : BSD3
-- Copyright   : (c) 2009-2010 Balazs Komuves
-- Author      : Balazs Komuves
-- Maintainer  : bkomuves (plus) hackage (at) gmail (dot) com
-- Stability   : experimental
-- Portability : requires FFI and CPP
-- Tested with : GHC 6.10.1
--------------------------------------------------------------------------------

-- | This is the same as the pure API, without the annoying alignment stuff. 
-- All functions use the default alignment.

{-# LANGUAGE CPP #-}
module Data.Bitmap.Simple 
  ( 
    module Data.Bitmap.Base
    
    -- * Creating bitmaps
  , emptyBitmap
  , emptyCloneBitmap
  , createSingleChannelBitmap
    -- * Using bitmaps
  , withBitmap
    -- * Mapping over bitmaps
  , componentMap
  , componentMap'
    -- * Cropping and extending
  , copySubImage
  , copySubImage'  
    -- * Flipping and mirroring
  , flipBitmap
  , mirrorBitmap
    -- * Casting
  , castBitmap
  -- , castChannel
    -- * Manipulating channels
  , combineChannels 
  , extractChannels 
  , extractSingleChannel 
    -- * Bilinear resampling
  , bilinearResample
  , bilinearResampleChannel  
    -- * Blending
  , blendBitmaps  
  , blendChannels  
    -- * Gamma correction
  , powerlawGammaCorrection
  , powerlawGammaCorrectionChannel   
{-  
    -- * Conversion to ByteString
  , bitmapToByteString  
-}  
  ) 
  where

--------------------------------------------------------------------------------

import Data.Word

import Foreign

import Data.ByteString (ByteString)
import qualified Data.ByteString as B
import qualified Data.ByteString.Internal as B

import Data.Bitmap.Base
import Data.Bitmap.Internal
import qualified Data.Bitmap.Pure as P

--------------------------------------------------------------------------------

-- | A bitmap filled with zero values.
emptyBitmap 
  :: PixelComponent t 
  => Size             -- ^ (width,height)
  -> NChn             -- ^ number of channels (components\/pixel)
  -> Bitmap t
emptyBitmap :: Size -> NChn -> Bitmap t
emptyBitmap Size
siz NChn
nchn = Size -> NChn -> Maybe NChn -> Bitmap t
forall t.
PixelComponent t =>
Size -> NChn -> Maybe NChn -> Bitmap t
P.emptyBitmap Size
siz NChn
nchn Maybe NChn
forall a. Maybe a
Nothing

-- | Creates a single channel bitmap from a function.
-- This is probably a bit slow.
createSingleChannelBitmap
  :: PixelComponent t 
  => Size               -- ^ (width,height)
  -> (Int -> Int -> t)  -- ^ the function used to create the bitmap
  -> Bitmap t
createSingleChannelBitmap :: Size -> (NChn -> NChn -> t) -> Bitmap t
createSingleChannelBitmap Size
siz NChn -> NChn -> t
fun = Size -> Maybe NChn -> (NChn -> NChn -> t) -> Bitmap t
forall t.
PixelComponent t =>
Size -> Maybe NChn -> (NChn -> NChn -> t) -> Bitmap t
P.createSingleChannelBitmap Size
siz Maybe NChn
forall a. Maybe a
Nothing NChn -> NChn -> t
fun

-- | Creates an empty bitmap with the same properties as the source.
emptyCloneBitmap 
  :: PixelComponent t 
  => Bitmap t           -- ^ source (only dimensions and such is used)
  -> Bitmap t           -- ^ new empty bitmap
emptyCloneBitmap :: Bitmap t -> Bitmap t
emptyCloneBitmap Bitmap t
bm = Bitmap t -> Maybe NChn -> Bitmap t
forall t. PixelComponent t => Bitmap t -> Maybe NChn -> Bitmap t
P.emptyCloneBitmap Bitmap t
bm Maybe NChn
forall a. Maybe a
Nothing
  
--------------------------------------------------------------------------------

-- | Warning: this is probably slow.
componentMap :: PixelComponent s => (s -> s) -> Bitmap s -> Bitmap s
componentMap :: (s -> s) -> Bitmap s -> Bitmap s
componentMap = (s -> s) -> Bitmap s -> Bitmap s
forall s. PixelComponent s => (s -> s) -> Bitmap s -> Bitmap s
P.componentMap

-- | Warning: this is probably slow.
componentMap' :: (PixelComponent s, PixelComponent t) => (s -> t) -> Bitmap s -> Bitmap t
componentMap' :: (s -> t) -> Bitmap s -> Bitmap t
componentMap' s -> t
f Bitmap s
bm = (s -> t) -> Bitmap s -> Maybe NChn -> Bitmap t
forall s t.
(PixelComponent s, PixelComponent t) =>
(s -> t) -> Bitmap s -> Maybe NChn -> Bitmap t
P.componentMap' s -> t
f Bitmap s
bm Maybe NChn
forall a. Maybe a
Nothing

--------------------------------------------------------------------------------

-- | Copies a subrectangle of the source image into a new image.  
copySubImage
  :: PixelComponent t 
  => Bitmap t         -- ^ source image
  -> Offset           -- ^ source rectangle offset
  -> Size             -- ^ source rectangle size
  -> Bitmap t
copySubImage :: Bitmap t -> Size -> Size -> Bitmap t
copySubImage = Bitmap t -> Size -> Size -> Bitmap t
forall t. PixelComponent t => Bitmap t -> Size -> Size -> Bitmap t
P.copySubImage

-- | Copy into a new \"black\" bitmap; common generalization of crop and extend.
copySubImage'
  :: PixelComponent t 
  => Bitmap t         -- ^ source image
  -> Offset           -- ^ source rectangle offset
  -> Size             -- ^ source rectangle size
  -> Size             -- ^ target image size
  -> Offset           -- ^ target rectangle offset
  -> Bitmap t
copySubImage' :: Bitmap t -> Size -> Size -> Size -> Size -> Bitmap t
copySubImage' = Bitmap t -> Size -> Size -> Size -> Size -> Bitmap t
forall t.
PixelComponent t =>
Bitmap t -> Size -> Size -> Size -> Size -> Bitmap t
P.copySubImage'
  
--------------------------------------------------------------------------------

-- | Flips the bitmap vertically.
flipBitmap 
  :: PixelComponent t 
  => Bitmap t
  -> Bitmap t
flipBitmap :: Bitmap t -> Bitmap t
flipBitmap Bitmap t
bm = Bitmap t -> Maybe NChn -> Bitmap t
forall t. PixelComponent t => Bitmap t -> Maybe NChn -> Bitmap t
P.flipBitmap Bitmap t
bm Maybe NChn
forall a. Maybe a
Nothing

-- | Flips the bitmap horizontally.
mirrorBitmap 
  :: PixelComponent t 
  => Bitmap t
  -> Bitmap t
mirrorBitmap :: Bitmap t -> Bitmap t
mirrorBitmap Bitmap t
bm = Bitmap t -> Maybe NChn -> Bitmap t
forall t. PixelComponent t => Bitmap t -> Maybe NChn -> Bitmap t
P.mirrorBitmap Bitmap t
bm Maybe NChn
forall a. Maybe a
Nothing

--------------------------------------------------------------------------------

-- | Converts between different component types.
castBitmap 
  :: (PixelComponent s, PixelComponent t)
  => Bitmap s               -- ^ source image
  -> Bitmap t 
castBitmap :: Bitmap s -> Bitmap t
castBitmap Bitmap s
bm1 = Bitmap s -> Maybe NChn -> Bitmap t
forall s t.
(PixelComponent s, PixelComponent t) =>
Bitmap s -> Maybe NChn -> Bitmap t
P.castBitmap Bitmap s
bm1 Maybe NChn
forall a. Maybe a
Nothing

--------------------------------------------------------------------------------

extractSingleChannel 
  :: PixelComponent t 
  => Bitmap t               -- ^ source image
  -> Int                    -- ^ source channel index
  -> Bitmap t
extractSingleChannel :: Bitmap t -> NChn -> Bitmap t
extractSingleChannel Bitmap t
bm1 NChn
j = Bitmap t -> Maybe NChn -> NChn -> Bitmap t
forall t.
PixelComponent t =>
Bitmap t -> Maybe NChn -> NChn -> Bitmap t
P.extractSingleChannel Bitmap t
bm1 Maybe NChn
forall a. Maybe a
Nothing NChn
j

extractChannels :: PixelComponent t => Bitmap t -> [Bitmap t]
extractChannels :: Bitmap t -> [Bitmap t]
extractChannels Bitmap t
bm = Bitmap t -> Maybe NChn -> [Bitmap t]
forall t. PixelComponent t => Bitmap t -> Maybe NChn -> [Bitmap t]
P.extractChannels Bitmap t
bm Maybe NChn
forall a. Maybe a
Nothing

combineChannels :: PixelComponent t => [Bitmap t] -> Bitmap t
combineChannels :: [Bitmap t] -> Bitmap t
combineChannels [Bitmap t]
bms = [Bitmap t] -> Maybe NChn -> Bitmap t
forall t. PixelComponent t => [Bitmap t] -> Maybe NChn -> Bitmap t
P.combineChannels [Bitmap t]
bms Maybe NChn
forall a. Maybe a
Nothing

--------------------------------------------------------------------------------

bilinearResample 
  :: PixelComponent t 
  => Bitmap t           -- ^ source image
  -> Size               -- ^ target image size
  -> Bitmap t  
bilinearResample :: Bitmap t -> Size -> Bitmap t
bilinearResample Bitmap t
bm Size
siz = Bitmap t -> Size -> Maybe NChn -> Bitmap t
forall t.
PixelComponent t =>
Bitmap t -> Size -> Maybe NChn -> Bitmap t
P.bilinearResample Bitmap t
bm Size
siz Maybe NChn
forall a. Maybe a
Nothing 

bilinearResampleChannel
  :: PixelComponent t 
  => Bitmap t           -- ^ source image
  -> Int                -- ^ source channel indexe
  -> Size               -- ^ target image size
  -> Bitmap t  
bilinearResampleChannel :: Bitmap t -> NChn -> Size -> Bitmap t
bilinearResampleChannel Bitmap t
bm NChn
j Size
siz = Bitmap t -> NChn -> Size -> Maybe NChn -> Bitmap t
forall t.
PixelComponent t =>
Bitmap t -> NChn -> Size -> Maybe NChn -> Bitmap t
P.bilinearResampleChannel Bitmap t
bm NChn
j Size
siz Maybe NChn
forall a. Maybe a
Nothing
  
--------------------------------------------------------------------------------

-- | Blends two bitmaps with the given weights; that is, the result is
-- the specified linear combination. If the values are outside the allowed
-- range (this can happen with the Word8, Word16, Word32 types and weights
-- whose sum is bigger than 1, or with a negative weight), then they are
-- clipped. The clipping /does not/ happen with the Float component type.
blendBitmaps
  :: PixelComponent t 
  => Float           -- ^ weight 1
  -> Float           -- ^ weight 2
  -> Bitmap t        -- ^ source image 1 
  -> Bitmap t        -- ^ source image 2
  -> Bitmap t
blendBitmaps :: Float -> Float -> Bitmap t -> Bitmap t -> Bitmap t
blendBitmaps Float
w1 Float
w2 Bitmap t
bm1 Bitmap t
bm2 = Float -> Float -> Bitmap t -> Bitmap t -> Maybe NChn -> Bitmap t
forall t.
PixelComponent t =>
Float -> Float -> Bitmap t -> Bitmap t -> Maybe NChn -> Bitmap t
P.blendBitmaps Float
w1 Float
w2 Bitmap t
bm1 Bitmap t
bm2 Maybe NChn
forall a. Maybe a
Nothing

blendChannels
  :: PixelComponent t 
  => Float           -- ^ weight 1
  -> Float           -- ^ weight 2
  -> Bitmap t        -- ^ source image 1 
  -> Int             -- ^ channel index 1
  -> Bitmap t        -- ^ source image 2
  -> Int             -- ^ channel index 2
  -> Bitmap t
blendChannels :: Float -> Float -> Bitmap t -> NChn -> Bitmap t -> NChn -> Bitmap t
blendChannels Float
w1 Float
w2 Bitmap t
bm1 NChn
ofs1 Bitmap t
bm2 NChn
ofs2 = Float
-> Float
-> Bitmap t
-> NChn
-> Bitmap t
-> NChn
-> Maybe NChn
-> Bitmap t
forall t.
PixelComponent t =>
Float
-> Float
-> Bitmap t
-> NChn
-> Bitmap t
-> NChn
-> Maybe NChn
-> Bitmap t
P.blendChannels Float
w1 Float
w2 Bitmap t
bm1 NChn
ofs1 Bitmap t
bm2 NChn
ofs2 Maybe NChn
forall a. Maybe a
Nothing
  
--------------------------------------------------------------------------------
  
-- | This is equivalent to @componentMap (\c -> c^gamma)@, except that
-- @(^)@ is defined only for integral exponents; but should be faster anyway.
powerlawGammaCorrection
  :: PixelComponent t 
  => Float              -- ^ gamma
  -> Bitmap t           -- ^ source image
  -> Bitmap t  
powerlawGammaCorrection :: Float -> Bitmap t -> Bitmap t
powerlawGammaCorrection Float
gamma Bitmap t
bm = Float -> Bitmap t -> Maybe NChn -> Bitmap t
forall t.
PixelComponent t =>
Float -> Bitmap t -> Maybe NChn -> Bitmap t
P.powerlawGammaCorrection Float
gamma Bitmap t
bm Maybe NChn
forall a. Maybe a
Nothing

powerlawGammaCorrectionChannel
  :: PixelComponent t 
  => Float              -- ^ gamma
  -> Bitmap t           -- ^ source image
  -> Int                -- ^ source channel indexe
  -> Bitmap t  
powerlawGammaCorrectionChannel :: Float -> Bitmap t -> NChn -> Bitmap t
powerlawGammaCorrectionChannel Float
gamma Bitmap t
bm NChn
j = Float -> Bitmap t -> NChn -> Maybe NChn -> Bitmap t
forall t.
PixelComponent t =>
Float -> Bitmap t -> NChn -> Maybe NChn -> Bitmap t
P.powerlawGammaCorrectionChannel Float
gamma Bitmap t
bm NChn
j Maybe NChn
forall a. Maybe a
Nothing
  
--------------------------------------------------------------------------------