--------------------------------------------------------------------------------
-- Module      : Data.Bitmap.Pure
-- 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
--------------------------------------------------------------------------------

-- | The pure, inmutable API.

{-# LANGUAGE CPP #-}
module Data.Bitmap.Pure 
  ( 
    module Data.Bitmap.Base
    
    -- * Creating bitmaps
  , emptyBitmap
  , cloneBitmap
  , emptyCloneBitmap
  , createSingleChannelBitmap
  , bitmapFromForeignPtrUnsafe
    -- * 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.ForeignPtr

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.IO as IO

import System.IO.Unsafe

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

-- | A bitmap filled with zero values.
-- Note: we /cannot/ guarantee the alignment
-- of the memory block (but typically it is aligned at least to machine word boundary),
-- but what we /can/ guarantee is that the rows are properly padded.
emptyBitmap 
  :: PixelComponent t 
  => Size             -- ^ (width,height)
  -> NChn             -- ^ number of channels (components\/pixel)
  -> Maybe Alignment  -- ^ the row alignment of the new image
  -> Bitmap t
emptyBitmap :: Size -> NChn -> Maybe NChn -> Bitmap t
emptyBitmap Size
siz NChn
nchn Maybe NChn
malign = IOBitmap t -> Bitmap t
forall t. IOBitmap t -> Bitmap t
unIOBitmap (IOBitmap t -> Bitmap t) -> IOBitmap t -> Bitmap t
forall a b. (a -> b) -> a -> b
$ IO (IOBitmap t) -> IOBitmap t
forall a. IO a -> a
unsafePerformIO (IO (IOBitmap t) -> IOBitmap t) -> IO (IOBitmap t) -> IOBitmap t
forall a b. (a -> b) -> a -> b
$ Size -> NChn -> Maybe NChn -> IO (IOBitmap t)
forall t.
PixelComponent t =>
Size -> NChn -> Maybe NChn -> IO (IOBitmap t)
IO.newIOBitmap Size
siz NChn
nchn Maybe NChn
malign

-- | Creates a single channel bitmap from a function.
-- This is probably a bit slow.
createSingleChannelBitmap
  :: PixelComponent t 
  => Size               -- ^ (width,height)
  -> Maybe Alignment    -- ^ the row alignment of the new image
  -> (Int -> Int -> t)  -- ^ the function used to create the bitmap
  -> Bitmap t
createSingleChannelBitmap :: Size -> Maybe NChn -> (NChn -> NChn -> t) -> Bitmap t
createSingleChannelBitmap Size
siz Maybe NChn
maling NChn -> NChn -> t
fun = IOBitmap t -> Bitmap t
forall t. IOBitmap t -> Bitmap t
unIOBitmap (IOBitmap t -> Bitmap t) -> IOBitmap t -> Bitmap t
forall a b. (a -> b) -> a -> b
$ IO (IOBitmap t) -> IOBitmap t
forall a. IO a -> a
unsafePerformIO (IO (IOBitmap t) -> IOBitmap t) -> IO (IOBitmap t) -> IOBitmap t
forall a b. (a -> b) -> a -> b
$ 
  Size -> Maybe NChn -> (NChn -> NChn -> t) -> IO (IOBitmap t)
forall t.
PixelComponent t =>
Size -> Maybe NChn -> (NChn -> NChn -> t) -> IO (IOBitmap t)
IO.createSingleChannelBitmap Size
siz Maybe NChn
maling 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)
  -> Maybe Alignment    -- ^ target alignment
  -> Bitmap t           -- ^ new empty bitmap
emptyCloneBitmap :: Bitmap t -> Maybe NChn -> Bitmap t
emptyCloneBitmap Bitmap t
bm1 Maybe NChn
malign = IOBitmap t -> Bitmap t
forall t. IOBitmap t -> Bitmap t
unIOBitmap (IOBitmap t -> Bitmap t) -> IOBitmap t -> Bitmap t
forall a b. (a -> b) -> a -> b
$ IO (IOBitmap t) -> IOBitmap t
forall a. IO a -> a
unsafePerformIO (IO (IOBitmap t) -> IOBitmap t) -> IO (IOBitmap t) -> IOBitmap t
forall a b. (a -> b) -> a -> b
$ 
  IOBitmap t -> Maybe NChn -> IO (IOBitmap t)
forall t.
PixelComponent t =>
IOBitmap t -> Maybe NChn -> IO (IOBitmap t)
IO.emptyCloneBitmap (Bitmap t -> IOBitmap t
forall t. Bitmap t -> IOBitmap t
IOBitmap Bitmap t
bm1) Maybe NChn
malign

-- | Clones a bitmap. The only effect of this in the pure 
-- setting should be that the alignment/padding can change.
-- You shouldn't normally use this function.
cloneBitmap 
  :: PixelComponent t 
  => Bitmap t           -- ^ source image
  -> Maybe Alignment    -- ^ target alignment
  -> Bitmap t
cloneBitmap :: Bitmap t -> Maybe NChn -> Bitmap t
cloneBitmap Bitmap t
bm1 Maybe NChn
malign = IOBitmap t -> Bitmap t
forall t. IOBitmap t -> Bitmap t
unIOBitmap (IOBitmap t -> Bitmap t) -> IOBitmap t -> Bitmap t
forall a b. (a -> b) -> a -> b
$ IO (IOBitmap t) -> IOBitmap t
forall a. IO a -> a
unsafePerformIO (IO (IOBitmap t) -> IOBitmap t) -> IO (IOBitmap t) -> IOBitmap t
forall a b. (a -> b) -> a -> b
$ 
  IOBitmap t -> Maybe NChn -> IO (IOBitmap t)
forall t.
PixelComponent t =>
IOBitmap t -> Maybe NChn -> IO (IOBitmap t)
IO.cloneBitmap (Bitmap t -> IOBitmap t
forall t. Bitmap t -> IOBitmap t
IOBitmap Bitmap t
bm1) Maybe NChn
malign

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

-- | Warning: this is probably slow.
componentMap :: PixelComponent s => (s -> s) -> Bitmap s -> Bitmap s
componentMap :: (s -> s) -> Bitmap s -> Bitmap s
componentMap s -> s
f Bitmap s
bm = IOBitmap s -> Bitmap s
forall t. IOBitmap t -> Bitmap t
unIOBitmap (IOBitmap s -> Bitmap s) -> IOBitmap s -> Bitmap s
forall a b. (a -> b) -> a -> b
$ IO (IOBitmap s) -> IOBitmap s
forall a. IO a -> a
unsafePerformIO (IO (IOBitmap s) -> IOBitmap s) -> IO (IOBitmap s) -> IOBitmap s
forall a b. (a -> b) -> a -> b
$ 
  (s -> s) -> IOBitmap s -> IO (IOBitmap s)
forall s.
PixelComponent s =>
(s -> s) -> IOBitmap s -> IO (IOBitmap s)
IO.componentMap s -> s
f (Bitmap s -> IOBitmap s
forall t. Bitmap t -> IOBitmap t
IOBitmap Bitmap s
bm)

-- | Warning: this is probably slow.
componentMap' :: (PixelComponent s, PixelComponent t) => (s -> t) -> Bitmap s -> Maybe Alignment -> Bitmap t
componentMap' :: (s -> t) -> Bitmap s -> Maybe NChn -> Bitmap t
componentMap' s -> t
f Bitmap s
bm Maybe NChn
malign = IOBitmap t -> Bitmap t
forall t. IOBitmap t -> Bitmap t
unIOBitmap (IOBitmap t -> Bitmap t) -> IOBitmap t -> Bitmap t
forall a b. (a -> b) -> a -> b
$ IO (IOBitmap t) -> IOBitmap t
forall a. IO a -> a
unsafePerformIO (IO (IOBitmap t) -> IOBitmap t) -> IO (IOBitmap t) -> IOBitmap t
forall a b. (a -> b) -> a -> b
$ 
  (s -> t) -> IOBitmap s -> Maybe NChn -> IO (IOBitmap t)
forall s t.
(PixelComponent s, PixelComponent t) =>
(s -> t) -> IOBitmap s -> Maybe NChn -> IO (IOBitmap t)
IO.componentMap' s -> t
f (Bitmap s -> IOBitmap s
forall t. Bitmap t -> IOBitmap t
IOBitmap Bitmap s
bm) Maybe NChn
malign

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

-- | 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
bm Size
ofs Size
siz = IOBitmap t -> Bitmap t
forall t. IOBitmap t -> Bitmap t
unIOBitmap (IOBitmap t -> Bitmap t) -> IOBitmap t -> Bitmap t
forall a b. (a -> b) -> a -> b
$ IO (IOBitmap t) -> IOBitmap t
forall a. IO a -> a
unsafePerformIO (IO (IOBitmap t) -> IOBitmap t) -> IO (IOBitmap t) -> IOBitmap t
forall a b. (a -> b) -> a -> b
$ 
  IOBitmap t -> Size -> Size -> IO (IOBitmap t)
forall t.
PixelComponent t =>
IOBitmap t -> Size -> Size -> IO (IOBitmap t)
IO.copySubImage (Bitmap t -> IOBitmap t
forall t. Bitmap t -> IOBitmap t
IOBitmap Bitmap t
bm) Size
ofs Size
siz

-- | 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
bm1 Size
ofs1 Size
rsiz Size
tsiz Size
ofs2 = IOBitmap t -> Bitmap t
forall t. IOBitmap t -> Bitmap t
unIOBitmap (IOBitmap t -> Bitmap t) -> IOBitmap t -> Bitmap t
forall a b. (a -> b) -> a -> b
$ IO (IOBitmap t) -> IOBitmap t
forall a. IO a -> a
unsafePerformIO (IO (IOBitmap t) -> IOBitmap t) -> IO (IOBitmap t) -> IOBitmap t
forall a b. (a -> b) -> a -> b
$
  IOBitmap t -> Size -> Size -> Size -> Size -> IO (IOBitmap t)
forall t.
PixelComponent t =>
IOBitmap t -> Size -> Size -> Size -> Size -> IO (IOBitmap t)
IO.copySubImage' (Bitmap t -> IOBitmap t
forall t. Bitmap t -> IOBitmap t
IOBitmap Bitmap t
bm1) Size
ofs1 Size
rsiz Size
tsiz Size
ofs2
  
--------------------------------------------------------------------------------

-- | Flips the bitmap vertically.
flipBitmap 
  :: PixelComponent t 
  => Bitmap t
  -> Maybe Alignment
  -> Bitmap t
flipBitmap :: Bitmap t -> Maybe NChn -> Bitmap t
flipBitmap Bitmap t
bm Maybe NChn
malign = IOBitmap t -> Bitmap t
forall t. IOBitmap t -> Bitmap t
unIOBitmap (IOBitmap t -> Bitmap t) -> IOBitmap t -> Bitmap t
forall a b. (a -> b) -> a -> b
$ IO (IOBitmap t) -> IOBitmap t
forall a. IO a -> a
unsafePerformIO (IO (IOBitmap t) -> IOBitmap t) -> IO (IOBitmap t) -> IOBitmap t
forall a b. (a -> b) -> a -> b
$ IOBitmap t -> Maybe NChn -> IO (IOBitmap t)
forall t.
PixelComponent t =>
IOBitmap t -> Maybe NChn -> IO (IOBitmap t)
IO.flipBitmap (Bitmap t -> IOBitmap t
forall t. Bitmap t -> IOBitmap t
IOBitmap Bitmap t
bm) Maybe NChn
malign

-- | Flips the bitmap horizontally.
mirrorBitmap 
  :: PixelComponent t 
  => Bitmap t
  -> Maybe Alignment
  -> Bitmap t
mirrorBitmap :: Bitmap t -> Maybe NChn -> Bitmap t
mirrorBitmap Bitmap t
bm Maybe NChn
malign = IOBitmap t -> Bitmap t
forall t. IOBitmap t -> Bitmap t
unIOBitmap (IOBitmap t -> Bitmap t) -> IOBitmap t -> Bitmap t
forall a b. (a -> b) -> a -> b
$ IO (IOBitmap t) -> IOBitmap t
forall a. IO a -> a
unsafePerformIO (IO (IOBitmap t) -> IOBitmap t) -> IO (IOBitmap t) -> IOBitmap t
forall a b. (a -> b) -> a -> b
$ IOBitmap t -> Maybe NChn -> IO (IOBitmap t)
forall t.
PixelComponent t =>
IOBitmap t -> Maybe NChn -> IO (IOBitmap t)
IO.mirrorBitmap (Bitmap t -> IOBitmap t
forall t. Bitmap t -> IOBitmap t
IOBitmap Bitmap t
bm) Maybe NChn
malign
  
--------------------------------------------------------------------------------

-- | Converts between different component types.
castBitmap 
  :: (PixelComponent s, PixelComponent t)
  => Bitmap s               -- ^ source image
  -> Maybe Alignment        -- ^ target image row alignment
  -> Bitmap t 
castBitmap :: Bitmap s -> Maybe NChn -> Bitmap t
castBitmap Bitmap s
bm1 Maybe NChn
malign = IOBitmap t -> Bitmap t
forall t. IOBitmap t -> Bitmap t
unIOBitmap (IOBitmap t -> Bitmap t) -> IOBitmap t -> Bitmap t
forall a b. (a -> b) -> a -> b
$ IO (IOBitmap t) -> IOBitmap t
forall a. IO a -> a
unsafePerformIO (IO (IOBitmap t) -> IOBitmap t) -> IO (IOBitmap t) -> IOBitmap t
forall a b. (a -> b) -> a -> b
$ 
  IOBitmap s -> Maybe NChn -> IO (IOBitmap t)
forall s t.
(PixelComponent s, PixelComponent t) =>
IOBitmap s -> Maybe NChn -> IO (IOBitmap t)
IO.castBitmap (Bitmap s -> IOBitmap s
forall t. Bitmap t -> IOBitmap t
IOBitmap Bitmap s
bm1) Maybe NChn
malign

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

extractSingleChannel 
  :: PixelComponent t 
  => Bitmap t               -- ^ source image
  -> Maybe Alignment        -- ^ target image row alignment
  -> Int                    -- ^ source channel index
  -> Bitmap t
extractSingleChannel :: Bitmap t -> Maybe NChn -> NChn -> Bitmap t
extractSingleChannel Bitmap t
bm1 Maybe NChn
malign NChn
j = IOBitmap t -> Bitmap t
forall t. IOBitmap t -> Bitmap t
unIOBitmap (IOBitmap t -> Bitmap t) -> IOBitmap t -> Bitmap t
forall a b. (a -> b) -> a -> b
$ IO (IOBitmap t) -> IOBitmap t
forall a. IO a -> a
unsafePerformIO (IO (IOBitmap t) -> IOBitmap t) -> IO (IOBitmap t) -> IOBitmap t
forall a b. (a -> b) -> a -> b
$ 
  IOBitmap t -> Maybe NChn -> NChn -> IO (IOBitmap t)
forall t.
PixelComponent t =>
IOBitmap t -> Maybe NChn -> NChn -> IO (IOBitmap t)
IO.extractSingleChannel (Bitmap t -> IOBitmap t
forall t. Bitmap t -> IOBitmap t
IOBitmap Bitmap t
bm1) Maybe NChn
malign NChn
j 

extractChannels :: PixelComponent t => Bitmap t -> Maybe Alignment -> [Bitmap t]
extractChannels :: Bitmap t -> Maybe NChn -> [Bitmap t]
extractChannels Bitmap t
bm Maybe NChn
malign = (IOBitmap t -> Bitmap t) -> [IOBitmap t] -> [Bitmap t]
forall a b. (a -> b) -> [a] -> [b]
map IOBitmap t -> Bitmap t
forall t. IOBitmap t -> Bitmap t
unIOBitmap ([IOBitmap t] -> [Bitmap t]) -> [IOBitmap t] -> [Bitmap t]
forall a b. (a -> b) -> a -> b
$ IO [IOBitmap t] -> [IOBitmap t]
forall a. IO a -> a
unsafePerformIO (IO [IOBitmap t] -> [IOBitmap t])
-> IO [IOBitmap t] -> [IOBitmap t]
forall a b. (a -> b) -> a -> b
$
  IOBitmap t -> Maybe NChn -> IO [IOBitmap t]
forall t.
PixelComponent t =>
IOBitmap t -> Maybe NChn -> IO [IOBitmap t]
IO.extractChannels (Bitmap t -> IOBitmap t
forall t. Bitmap t -> IOBitmap t
IOBitmap Bitmap t
bm) Maybe NChn
malign 

combineChannels :: PixelComponent t => [Bitmap t] -> Maybe Alignment -> Bitmap t
combineChannels :: [Bitmap t] -> Maybe NChn -> Bitmap t
combineChannels [Bitmap t]
bms Maybe NChn
malign = IOBitmap t -> Bitmap t
forall t. IOBitmap t -> Bitmap t
unIOBitmap (IOBitmap t -> Bitmap t) -> IOBitmap t -> Bitmap t
forall a b. (a -> b) -> a -> b
$ IO (IOBitmap t) -> IOBitmap t
forall a. IO a -> a
unsafePerformIO (IO (IOBitmap t) -> IOBitmap t) -> IO (IOBitmap t) -> IOBitmap t
forall a b. (a -> b) -> a -> b
$
  [IOBitmap t] -> Maybe NChn -> IO (IOBitmap t)
forall t.
PixelComponent t =>
[IOBitmap t] -> Maybe NChn -> IO (IOBitmap t)
IO.combineChannels ((Bitmap t -> IOBitmap t) -> [Bitmap t] -> [IOBitmap t]
forall a b. (a -> b) -> [a] -> [b]
map Bitmap t -> IOBitmap t
forall t. Bitmap t -> IOBitmap t
IOBitmap [Bitmap t]
bms) Maybe NChn
malign

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

bilinearResample 
  :: PixelComponent t 
  => Bitmap t           -- ^ source image
  -> Size               -- ^ target image size
  -> Maybe Alignment    -- ^ target image row alignment
  -> Bitmap t  
bilinearResample :: Bitmap t -> Size -> Maybe NChn -> Bitmap t
bilinearResample Bitmap t
bm Size
siz Maybe NChn
malign = IOBitmap t -> Bitmap t
forall t. IOBitmap t -> Bitmap t
unIOBitmap (IOBitmap t -> Bitmap t) -> IOBitmap t -> Bitmap t
forall a b. (a -> b) -> a -> b
$ IO (IOBitmap t) -> IOBitmap t
forall a. IO a -> a
unsafePerformIO (IO (IOBitmap t) -> IOBitmap t) -> IO (IOBitmap t) -> IOBitmap t
forall a b. (a -> b) -> a -> b
$ 
  IOBitmap t -> Size -> Maybe NChn -> IO (IOBitmap t)
forall t.
PixelComponent t =>
IOBitmap t -> Size -> Maybe NChn -> IO (IOBitmap t)
IO.bilinearResample (Bitmap t -> IOBitmap t
forall t. Bitmap t -> IOBitmap t
IOBitmap Bitmap t
bm) Size
siz Maybe NChn
malign

bilinearResampleChannel
  :: PixelComponent t 
  => Bitmap t           -- ^ source image
  -> Int                -- ^ source channel indexe
  -> Size               -- ^ target image size
  -> Maybe Alignment    -- ^ target image row alignment
  -> Bitmap t  
bilinearResampleChannel :: Bitmap t -> NChn -> Size -> Maybe NChn -> Bitmap t
bilinearResampleChannel Bitmap t
bm NChn
j Size
siz Maybe NChn
malign = IOBitmap t -> Bitmap t
forall t. IOBitmap t -> Bitmap t
unIOBitmap (IOBitmap t -> Bitmap t) -> IOBitmap t -> Bitmap t
forall a b. (a -> b) -> a -> b
$ IO (IOBitmap t) -> IOBitmap t
forall a. IO a -> a
unsafePerformIO (IO (IOBitmap t) -> IOBitmap t) -> IO (IOBitmap t) -> IOBitmap t
forall a b. (a -> b) -> a -> b
$ 
  IOBitmap t -> NChn -> Size -> Maybe NChn -> IO (IOBitmap t)
forall t.
PixelComponent t =>
IOBitmap t -> NChn -> Size -> Maybe NChn -> IO (IOBitmap t)
IO.bilinearResampleChannel (Bitmap t -> IOBitmap t
forall t. Bitmap t -> IOBitmap t
IOBitmap Bitmap t
bm) NChn
j Size
siz Maybe NChn
malign
  
--------------------------------------------------------------------------------

-- | 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
  -> Maybe Alignment -- ^ target alignment
  -> Bitmap t
blendBitmaps :: Float -> Float -> Bitmap t -> Bitmap t -> Maybe NChn -> Bitmap t
blendBitmaps Float
w1 Float
w2 Bitmap t
bm1 Bitmap t
bm2 Maybe NChn
malign = IOBitmap t -> Bitmap t
forall t. IOBitmap t -> Bitmap t
unIOBitmap (IOBitmap t -> Bitmap t) -> IOBitmap t -> Bitmap t
forall a b. (a -> b) -> a -> b
$ IO (IOBitmap t) -> IOBitmap t
forall a. IO a -> a
unsafePerformIO (IO (IOBitmap t) -> IOBitmap t) -> IO (IOBitmap t) -> IOBitmap t
forall a b. (a -> b) -> a -> b
$ 
  Float
-> Float
-> IOBitmap t
-> IOBitmap t
-> Maybe NChn
-> IO (IOBitmap t)
forall t.
PixelComponent t =>
Float
-> Float
-> IOBitmap t
-> IOBitmap t
-> Maybe NChn
-> IO (IOBitmap t)
IO.blendBitmaps Float
w1 Float
w2 (Bitmap t -> IOBitmap t
forall t. Bitmap t -> IOBitmap t
IOBitmap Bitmap t
bm1) (Bitmap t -> IOBitmap t
forall t. Bitmap t -> IOBitmap t
IOBitmap Bitmap t
bm2) Maybe NChn
malign

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
  -> Maybe Alignment -- ^ target alignment
  -> Bitmap t
blendChannels :: Float
-> Float
-> Bitmap t
-> NChn
-> Bitmap t
-> NChn
-> Maybe NChn
-> Bitmap t
blendChannels Float
w1 Float
w2 Bitmap t
bm1 NChn
ofs1 Bitmap t
bm2 NChn
ofs2 Maybe NChn
malign = IOBitmap t -> Bitmap t
forall t. IOBitmap t -> Bitmap t
unIOBitmap (IOBitmap t -> Bitmap t) -> IOBitmap t -> Bitmap t
forall a b. (a -> b) -> a -> b
$ IO (IOBitmap t) -> IOBitmap t
forall a. IO a -> a
unsafePerformIO (IO (IOBitmap t) -> IOBitmap t) -> IO (IOBitmap t) -> IOBitmap t
forall a b. (a -> b) -> a -> b
$ 
  Float
-> Float
-> IOBitmap t
-> NChn
-> IOBitmap t
-> NChn
-> Maybe NChn
-> IO (IOBitmap t)
forall t.
PixelComponent t =>
Float
-> Float
-> IOBitmap t
-> NChn
-> IOBitmap t
-> NChn
-> Maybe NChn
-> IO (IOBitmap t)
IO.blendChannels Float
w1 Float
w2 (Bitmap t -> IOBitmap t
forall t. Bitmap t -> IOBitmap t
IOBitmap Bitmap t
bm1) NChn
ofs1 (Bitmap t -> IOBitmap t
forall t. Bitmap t -> IOBitmap t
IOBitmap Bitmap t
bm2) NChn
ofs2 Maybe NChn
malign
  
--------------------------------------------------------------------------------
  
-- | 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
  -> Maybe Alignment    -- ^ target image row alignment
  -> Bitmap t  
powerlawGammaCorrection :: Float -> Bitmap t -> Maybe NChn -> Bitmap t
powerlawGammaCorrection Float
gamma Bitmap t
bm Maybe NChn
malign = IOBitmap t -> Bitmap t
forall t. IOBitmap t -> Bitmap t
unIOBitmap (IOBitmap t -> Bitmap t) -> IOBitmap t -> Bitmap t
forall a b. (a -> b) -> a -> b
$ IO (IOBitmap t) -> IOBitmap t
forall a. IO a -> a
unsafePerformIO (IO (IOBitmap t) -> IOBitmap t) -> IO (IOBitmap t) -> IOBitmap t
forall a b. (a -> b) -> a -> b
$ 
  Float -> IOBitmap t -> Maybe NChn -> IO (IOBitmap t)
forall t.
PixelComponent t =>
Float -> IOBitmap t -> Maybe NChn -> IO (IOBitmap t)
IO.powerlawGammaCorrection Float
gamma (Bitmap t -> IOBitmap t
forall t. Bitmap t -> IOBitmap t
IOBitmap Bitmap t
bm) Maybe NChn
malign

powerlawGammaCorrectionChannel
  :: PixelComponent t 
  => Float              -- ^ gamma
  -> Bitmap t           -- ^ source image
  -> Int                -- ^ source channel indexe
  -> Maybe Alignment    -- ^ target image row alignment
  -> Bitmap t  
powerlawGammaCorrectionChannel :: Float -> Bitmap t -> NChn -> Maybe NChn -> Bitmap t
powerlawGammaCorrectionChannel Float
gamma Bitmap t
bm NChn
j Maybe NChn
malign = IOBitmap t -> Bitmap t
forall t. IOBitmap t -> Bitmap t
unIOBitmap (IOBitmap t -> Bitmap t) -> IOBitmap t -> Bitmap t
forall a b. (a -> b) -> a -> b
$ IO (IOBitmap t) -> IOBitmap t
forall a. IO a -> a
unsafePerformIO (IO (IOBitmap t) -> IOBitmap t) -> IO (IOBitmap t) -> IOBitmap t
forall a b. (a -> b) -> a -> b
$ 
  Float -> IOBitmap t -> NChn -> Maybe NChn -> IO (IOBitmap t)
forall t.
PixelComponent t =>
Float -> IOBitmap t -> NChn -> Maybe NChn -> IO (IOBitmap t)
IO.powerlawGammaCorrectionChannel Float
gamma (Bitmap t -> IOBitmap t
forall t. Bitmap t -> IOBitmap t
IOBitmap Bitmap t
bm) NChn
j Maybe NChn
malign
  
--------------------------------------------------------------------------------

{-
-- | Note that the data is /shared/; and also that the resulting ByteString
-- is encoded using the host machine's endianness.
bitmapToByteString :: PixelComponent t => Bitmap t -> ByteString
bitmapToByteString bm = bs where
  bs = B.fromForeignPtr (castForeignPtr $ bitmapPtr bm) 0 n
  n = bitmapSizeInBytes bm 
-}

{-  
-- | As its name says, this pretty much unsafe!
reallyUnsafeBitmapFromByteString :: ByteString -> Size -> NChn -> Padding -> Bitmap t
reallyUnsafeBitmapFromByteString bs siz nchn pad = 
  if n > len || ofs /= 0 
    then error "reallyUnsafeBitmapFromByteString: better than segfault :)"
    else bm   
  where
    bm = Bitmap 
      { bitmapSize = siz
      , bitmapNChannels = nchn
      , bitmapPtr = fptr 
      , bitmapRowPadding = pad
      , bitmapRowAlignment = 1
      } :: Bitmap t
    n = bitmapSizeInBytes bm
    (fptr,ofs,len) = B.toForeignPtr bm
-}
  
--------------------------------------------------------------------------------