packages feed

JuicyPixels-repa (empty) → 0.1

raw patch · 4 files changed

+346/−0 lines, 4 filesdep +JuicyPixelsdep +basedep +bytestringsetup-changed

Dependencies added: JuicyPixels, base, bytestring, repa, vector

Files

+ Codec/Picture/Repa.hs view
@@ -0,0 +1,252 @@+{-# LANGUAGE EmptyDataDecls, FlexibleInstances, TypeSynonymInstances, MultiParamTypeClasses #-}+module Codec.Picture.Repa+       ( -- * Primitive types and operations+         Img, imgData+       , convertImage+         -- * Generic interface+       , readImage, decodeImage+         -- * Monomorphic image decoding functions+       , readImageRGBA, readImageRGB, readImageR, readImageG, readImageB+       , decodeImageRGBA, decodeImageRGB, decodeImageR, decodeImageG, decodeImageB+       -- * Image Representations (Phantom Types)+       , RGBA, RGB, R, G, B+       -- * Helper Functions (useful for OpenGL etc.) +       , toVector+       , toForeignPtr+       , reverseColorChannel+       , flipHorizontally, flipVertically+       -- * Internal Functionallity (exported for advanced uses)+       , ToRGBAChannels(..)+       ) where+import qualified Data.Array.Repa as R+import Data.Array.Repa ((:.), Array, (:.)(..), Z(..), DIM3, backpermute, extent)+import qualified Codec.Picture as P+import Codec.Picture hiding (readImage, decodeImage)+import Codec.Picture.Types hiding (convertImage)+import qualified Data.Vector.Storable as S+import qualified Data.Vector.Unboxed as VU+import Foreign.ForeignPtr+import Data.Word+import Control.Monad+import Data.ByteString as B++-- |An all-red image+data R++-- |An all-green image+data G++-- |An all-blue image+data B++-- |A 32-bit image with full red, green, blue and alpha channels.+--+-- The image is stored as Height x Width x ColorChannel.+--+-- The color channel is stored in RGBA order.  For the common OpenGL ordering+-- users might want to use 'reverseColorChannel'.+data RGBA++-- |A 24-bit image with red, green and blue channels+data RGB++-- |@Img a@ is an image where the phantom type 'a' indicates the image format+--+-- All images are held in a three dimensional 'repa' array.  If the image+-- format is only two dimensional (ex: R, G, or B) then the shape is @Z :. y :. x :. 1@.+data Img a = Img { imgData :: Array DIM3 Word8 }++-- |By default, the color channel for 'RGBA' indexes 0 -> R, 1 -> G, 2+-- -> B, 3 -> A.  This is the AGBR byte ordering in OpenGL.  For+-- rendering with OpenGL's RGBA PixelFormat be sure to call+-- reverseColorChannel before converting to a Vector (or directly to+-- bytestring via 'repa-bytestring').+reverseColorChannel :: Img a -> Img a+reverseColorChannel (Img r) = Img (R.backpermute e order r)+  where+  e@(Z :. row :. col :. z)  = R.extent r+  order (Z :. r :. c :. z') = Z :. r :. c :. z - z' - 1++readImageRGBA :: FilePath -> IO (Either String (Img RGBA))+readImageRGBA = readImage++readImageRGB :: FilePath -> IO (Either String (Img RGB))+readImageRGB = readImage++readImageB :: FilePath -> IO (Either String (Img B))+readImageB = readImage++readImageG :: FilePath -> IO (Either String (Img G))+readImageG = readImage++readImageR :: FilePath -> IO (Either String (Img R))+readImageR = readImage++decodeImageRGBA :: ByteString -> Either String (Img RGBA)+decodeImageRGBA = decodeImage++decodeImageRGB :: ByteString -> Either String (Img RGB)+decodeImageRGB = decodeImage++decodeImageR :: ByteString -> Either String (Img R)+decodeImageR = decodeImage++decodeImageG :: ByteString -> Either String (Img G)+decodeImageG = decodeImage++decodeImageB :: ByteString -> Either String (Img B)+decodeImageB = decodeImage++class DecodeImage a where+  decodeImage :: ByteString -> Either String (Img a)++instance DecodeImage RGBA where+  decodeImage = decodeImageRGBA+instance DecodeImage RGB where+  decodeImage = decodeImageRGB+instance DecodeImage R where+  decodeImage = decodeImageR+instance DecodeImage G where+  decodeImage = decodeImageG+instance DecodeImage B where+  decodeImage = decodeImageB++readImage :: DecodeImage a => FilePath -> IO (Either String (Img a))+readImage f = liftM decodeImage (B.readFile f)++-- | O(n)  returning (pointer, length, offset)+toForeignPtr :: Img RGBA -> (ForeignPtr Word8, Int, Int)+toForeignPtr = S.unsafeToForeignPtr . S.convert . R.toVector . imgData++-- |Convert an 'Img' to a storable 'Vector', often useful for OpenGL+-- and other C interfaces.  Notice the format of the data depends on+-- the type of the 'Img a'. O(n)+toVector :: Img a -> S.Vector Word8+toVector (Img a) = S.convert (R.toVector a)++-- Helper functions --+getChannel :: Int -> PixelRGBA8 -> Word8+getChannel 0 (PixelRGBA8 r g b a) = r+getChannel 1 (PixelRGBA8 r g b a) = g+getChannel 2 (PixelRGBA8 r g b a) = b+getChannel _ (PixelRGBA8 r g b a) = a++-- |For any of the JuicyPixel pixels, get the RGBA values+getChan :: (ToRGBAChannels p) => Int -> p -> Word8+getChan c = getChannel c . toRGBAChannels++-- |For any of the JuicyPixel images, get a channel of a particular pixel+getPixel :: (ToRGBAChannels p, Pixel p) => Int -> Int -> Int -> Image p -> Word8+getPixel x y z p = getChan z (pixelAt p x y)++-- Helper class and instances+class ToRGBAChannels a where+  toRGBAChannels :: a -> PixelRGBA8++instance ToRGBAChannels PixelRGBA8 where+  toRGBAChannels = id++instance ToRGBAChannels PixelYCbCr8 where+  toRGBAChannels = promotePixel . (id :: PixelRGB8 -> PixelRGB8) . convertPixel++instance ToRGBAChannels PixelRGB8 where+  toRGBAChannels = promotePixel++instance ToRGBAChannels PixelYA8 where+  toRGBAChannels = promotePixel+  +instance ToRGBAChannels Pixel8 where+  toRGBAChannels = promotePixel++zeroCopyConvert :: Int -> Image a -> Img b+zeroCopyConvert cc (Image w h dat) =+    let (ptr,off,len) = S.unsafeToForeignPtr dat+        sh = Z :. h :. w :. cc+    in if off == 0+       then flipVertically . Img . R.unsafeFromForeignPtr sh   $  ptr+       else flipVertically . Img . R.fromVector sh $ VU.convert $ dat++-- Now we start the instances needing exported++-- |Converts from 'JuicyPixels' type to the repa-based 'Img' type.+class ConvertImage a b where+  -- |Converts from 'JuicyPixels' type (Usually 'Image' or+  -- 'DynamicImage' to the repa-based 'Img' type.+  convertImage :: a -> Img b++instance ConvertImage DynamicImage RGBA where+  convertImage (ImageY8 i) = convertImage i+  convertImage (ImageYA8 i) = convertImage i+  convertImage (ImageRGB8 i) = convertImage i+  convertImage (ImageRGBA8 i) = zeroCopyConvert 4 i+  convertImage (ImageYCbCr8 i) = convertImage i+  +instance ConvertImage DynamicImage RGB where+  convertImage (ImageY8 i) = convertImage i+  convertImage (ImageYA8 i) = convertImage i+  convertImage (ImageRGB8 i) = zeroCopyConvert 3 i+  convertImage (ImageRGBA8 i) = convertImage i+  convertImage (ImageYCbCr8 i) = convertImage i+  +instance ConvertImage DynamicImage R where+  convertImage (ImageY8 i) = convertImage i+  convertImage (ImageYA8 i) = convertImage i+  convertImage (ImageRGB8 i) = convertImage i+  convertImage (ImageRGBA8 i) = convertImage i+  convertImage (ImageYCbCr8 i) = convertImage i+  +instance ConvertImage DynamicImage G where+  convertImage (ImageY8 i) = convertImage i+  convertImage (ImageYA8 i) = convertImage i+  convertImage (ImageRGB8 i) = convertImage i+  convertImage (ImageRGBA8 i) = convertImage i+  convertImage (ImageYCbCr8 i) = convertImage i+  +instance ConvertImage DynamicImage B where+  convertImage (ImageY8 i) = convertImage i+  convertImage (ImageYA8 i) = convertImage i+  convertImage (ImageRGB8 i) = convertImage i+  convertImage (ImageRGBA8 i) = convertImage i+  convertImage (ImageYCbCr8 i) = convertImage i++instance (ToRGBAChannels a, Pixel a) => ConvertImage (Image a) RGBA where+  convertImage p@(Image w h dat) =+    let z = 4+    in Img $ R.fromFunction (Z :. h :. w :. z) +                            (\(Z :. y :. x :. z') -> getPixel x y (z - z' - 1) p)+  +instance (ToRGBAChannels a, Pixel a) => ConvertImage (Image a) RGB where+  convertImage p@(Image w h dat) =+    let z = 3+    in Img $ R.fromFunction (Z :. h :. w :. z)+                            (\(Z :. y :. x :. z') -> getPixel x y (z' - z -1) p)++instance (ToRGBAChannels a, Pixel a) => ConvertImage (Image a) R where+  convertImage p@(Image w h dat) =+    let z = 1+    in Img $ R.fromFunction (Z :. h :. w :. z)+                            (\(Z :. y :. x :. z) -> getPixel x y 0 p)+       +instance (ToRGBAChannels a, Pixel a) => ConvertImage (Image a) G where+  convertImage p@(Image w h dat) =+    let z = 1+    in Img $ R.fromFunction (Z :. h :. w :. z)+                            (\(Z :. y :. x :. z) -> getPixel x y 1 p)+       +instance (ToRGBAChannels a, Pixel a) => ConvertImage (Image a) B where+  convertImage p@(Image w h dat) =+    let z = 1+    in Img $ R.fromFunction (Z :. h :. w :. z)+                            (\(Z :. y :. x :. z) -> getPixel x y 2 p)++flipVertically :: Img a -> Img a+flipVertically (Img rp) = Img (backpermute e order rp)+ where+ e@(Z :. row :. col :. z) = extent rp+ order (Z :. oldRow :. oldCol :. oldChan) = Z :. row - oldRow - 1 :. oldCol :. oldChan++flipHorizontally :: Img a -> Img b+flipHorizontally (Img rp) = Img (backpermute e order rp)+ where+ e@(Z :. row :. col :. z) = extent rp+ order (Z :. oldRow :. oldCol :. oldChan) = Z :. oldRow :. col - oldCol - 1 :. oldChan
+ JuicyPixels-repa.cabal view
@@ -0,0 +1,62 @@+-- Juicy.Pixels.Interface.cabal auto-generated by cabal init. For+-- additional options, see+-- http://www.haskell.org/cabal/release/cabal-latest/doc/users-guide/authors.html#pkg-descr.+-- The name of the package.+Name:                JuicyPixels-repa++-- The package version. See the Haskell package versioning policy+-- (http://www.haskell.org/haskellwiki/Package_versioning_policy) for+-- standards guiding when and how versions should be incremented.+Version:             0.1++-- A short (one-line) description of the package.+Synopsis:            Convenience functions to obtain array representations of images.++-- A longer description of the package.+Description:         This wraps the Juicy.Pixels library to convert into 'Repa' and +                     'Data.Vector.Storable' formats.++-- The license under which the package is released.+License:             BSD3++-- The file containing the license text.+License-file:        LICENSE++-- The package author(s).+Author:              Thomas M. DuBuisson++-- An email address to which users can send suggestions, bug reports,+-- and patches.+Maintainer:          Thomas.DuBuisson@gmail.com++-- A copyright notice.+-- Copyright:           ++Category:            Graphics++Build-type:          Simple++-- Extra files to be distributed with the package, such as examples or+-- a README.+-- Extra-source-files:  ++-- Constraint on the version of Cabal needed to build this package.+Cabal-version:       >=1.6+++Library+  -- Modules exported by the library.+  Exposed-modules:     Codec.Picture.Repa+  +  -- Packages needed in order to build this package.+  Build-depends:       base >= 4.0 && < 5, repa >= 2.1 && < 2.3+                    , JuicyPixels >= 1.1 && < 1.2+                    , vector >= 0.9 && < 0.10+                    , bytestring >= 0.9 && < 0.10+  +  -- Modules not exported by this package.+  -- Other-modules:       +  +  -- Extra tools (e.g. alex, hsc2hs, ...) needed to build the source.+  -- Build-tools:         +  
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c)2012, Thomas M. DuBuisson++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Thomas M. DuBuisson nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain