{-# OPTIONS -Wall #-} -------------------------------------------------------------------------------- -- | -- Module : Graphics.Rendering.OpenVG.VG.Images -- Copyright : (c) Stephen Tetley 2008-2014 -- License : BSD3 -- -- Maintainer : Stephen Tetley -- Stability : unstable -- Portability : GHC -- -- This module corresponds to section 10 (Images) -- of the OpenVG 1.0.1 specs. -- -- -------------------------------------------------------------------------------- module Graphics.Rendering.OpenVG.VG.Images ( -- * Image quality ImageQuality(..), imageQuality, -- * Image formats ImageFormat(..), -- * Pixel data Stride, PixelData, -- * Creating and destroying images maxImageWidth, maxImageHeight, maxImagePixels, maxImageBytes, createImage, destroyImage, withImage, -- * Querying images imageFormat, imageWidth, imageHeight, -- * Reading and writing image pixels clearImage, imageSubData, getImageSubData, -- * Copying pixels between images copyImage, -- * Drawing images to the drawing surface ImageMode(..), drawImageMode, drawImage, -- * Reading and writing drawing surface pixels setPixels, writePixels, getPixels, readPixels, -- * Copying portions of the drawing surface copyPixels ) where import Graphics.Rendering.OpenVG.VG.Parameters import Graphics.Rendering.OpenVG.VG.Utils ( bitwiseOr, marshalBool, unSizeM ) import Graphics.Rendering.OpenVG.Raw.VG.Core101 ( VGenum, VGint, VGImage ) import Graphics.Rendering.OpenVG.Raw.VG.Images import Graphics.Rendering.OpenGL.GL.CoordTrans ( Position(..), Size (..) ) import Graphics.Rendering.OpenGL.GL.StateVar ( GettableStateVar, makeGettableStateVar, SettableStateVar, makeSettableStateVar ) import Foreign.Ptr ( Ptr ) -------------------------------------------------------------------------------- -- Image quality -- | Resampling quality to be used when drawing images. data ImageQuality = Nonantialiased | Faster | Better deriving ( Eq, Ord, Show ) -- | Set the image quality. -- -- 'imageQuality' is a write-only state variable corresponding to -- @VG_IMAGE_QUALITY@: -- -- > vgSeti(VG_IMAGE_QUALITY, quality); -- imageQuality :: SettableStateVar ImageQuality imageQuality = makeSettableStateVar $ seti ImageQuality . fromIntegral . marshalImageQuality -------------------------------------------------------------------------------- -- Image formats -- | Image formats and colur spaces supported by OpenVG. -- -- \*\* NOTE - ImageFormat enumerates /all/ the image formats -- supported by OpenVG. ShivaVG currently only supports -- @sRGBA_8888@. \*\* -- data ImageFormat = -- RGB{A,X} channel ordering SRGBX8888 | SRGBA8888 | SRGBA8888Pre | SRGB565 | SRGBA5551 | SRGBA4444 | SL8 | LRGBX8888 | LRGBA8888 | LRGBA8888Pre | LL8 | A8 | BW1 -- {A,X}RGB channel ordering | SXRGB8888 | SARGB8888 | SARGB8888Pre | SARGB1555 | SARGB4444 | LXRGB8888 | LARGB8888 | LARGB8888Pre -- BGR{A,X} channel ordering | SBGRX8888 | SBGRA8888 | SBGRA8888Pre | SBGR565 | SBGRA5551 | SBGRA4444 | LBGRX8888 | LBGRA8888 | LBGRA8888Pre -- {A,X}BGR channel ordering | SXBGR8888 | SABGR8888 | SABGR8888Pre | SABGR1555 | SABGR4444 | LXBGR8888 | LABGR8888 | LABGR8888Pre deriving ( Eq, Ord, Show ) -------------------------------------------------------------------------------- -- Pixel data -- Derived from HOpenGL -- NOTES - How do you create PixelData ? type Stride = VGint -- Opaque handle to pixel data. -- -- \*\* NOTE - ShivaVG currently only supports @sRGBA_8888@. \*\* -- data PixelData a = PixelData ImageFormat Stride (Ptr a) deriving ( Eq, Ord, Show ) withPixelData :: PixelData a -> (VGenum -> Stride -> Ptr a -> b) -> b withPixelData (PixelData image_format stride ptr) f = f (marshalImageFormat image_format) stride ptr -------------------------------------------------------------------------------- -- Creating and destroying images -- | Get the maximum available width for the 'createImage' function. -- -- 'maxImageWidth' is a read-only state variable corresponding to -- @VG_MAX_IMAGE_WIDTH@: -- -- > VGint imageMaxWidth = vgGeti(VG_MAX_IMAGE_WIDTH); -- maxImageWidth :: GettableStateVar VGint maxImageWidth = makeGettableStateVar $ geti MaxImageWidth -- | Get the maximum available width for the 'createImage' function. -- -- 'maxImageWidth' is a read-only state variable corresponding to -- @VG_MAX_IMAGE_HEIGHT@: -- -- > VGint imageMaxWidth = vgGeti(VG_MAX_IMAGE_WIDTH); -- maxImageHeight :: GettableStateVar VGint maxImageHeight = makeGettableStateVar $ geti MaxImageHeight -- | Get the largest number of pixels that may make up an image -- supported by OpenVG implementation. -- -- 'maxImagePixels' is a read-only state variable corresponding to -- @VG_MAX_IMAGE_PIXELS@: -- -- > VGint imageMaxPixels = vgGeti(VG_MAX_IMAGE_PIXELS); -- maxImagePixels :: GettableStateVar VGint maxImagePixels = makeGettableStateVar $ geti MaxImagePixels -- | Get the largest number of bytes that may make up an image -- supported by OpenVG implementation. -- -- 'maxImageBytes' is a read-only state variable corresponding to -- @VG_MAX_IMAGE_BYTES@: -- -- > VGint imageMaxBytes = vgGeti(VG_MAX_IMAGE_BYTES); -- maxImageBytes :: GettableStateVar VGint maxImageBytes = makeGettableStateVar $ geti MaxImageBytes -- | Create an image and return a handle to it. -- -- 'createImage' corresponds to the OpenVG function -- @vgCreateImage@. -- -- \*\* NOTE - ShivaVG currently only supports @sRGBA_8888@ - -- this function throws a runtime error for other formats. \*\* -- createImage :: ImageFormat -> Size -> [ImageQuality] -> IO VGImage createImage SRGBA8888 sz qs = unSizeM (\w h -> vgCreateImage (marshalImageFormat SRGBA8888) w h (bitwiseOr marshalImageQuality qs)) sz createImage _ _ _ = error $ "unsupported image format" -- | Destroy the image and the resources assciated with it. -- -- 'destroyImage' corresponds to the OpenVG function -- @vgDestroyImage@. -- destroyImage :: VGImage -> IO () destroyImage = vgDestroyImage -- | Create an image, run an action on it, destroy the image. -- -- 'withImage' is a convenience function defined within the -- Haskell binding it does not have a corresponding OpenVG -- function. -- withImage :: ImageFormat -> Size -> [ImageQuality] -> (VGImage -> IO a) -> IO a withImage fmt sz qual action = do img <- createImage fmt sz qual ans <- action img destroyImage img return ans -------------------------------------------------------------------------------- -- Querying images -- | Get the image format. -- -- 'imageFormat' provides access to the OpenVG state variable -- @VG_IMAGE_FORMAT@: -- -- > VGImageFormat imageFormat = -- > (VGImageFormat)vgGetParameteri(image, VG_IMAGE_FORMAT); -- imageFormat :: VGImage -> GettableStateVar ImageFormat imageFormat h = makeGettableStateVar $ getParameteri h vg_IMAGE_FORMAT >>= return . unmarshalImageFormat . fromIntegral -- | Get the image width. -- -- 'imageWidth' is a read-only state variable corresponding to -- @VG_IMAGE_WIDTH@: -- -- > VGint imageWidth = vgGetParameteri(image, VG_IMAGE_WIDTH); -- imageWidth :: VGImage -> GettableStateVar VGint imageWidth = makeGettableStateVar . flip getParameteri vg_IMAGE_WIDTH -- | Get the image height. -- -- 'imageHeight' is a read-only state variable corresponding to -- @VG_IMAGE_HEIGHT@: -- -- > VGint imageHeight = vgGetParameteri(image, VG_IMAGE_HEIGHT); -- imageHeight :: VGImage -> GettableStateVar VGint imageHeight = makeGettableStateVar . flip getParameteri vg_IMAGE_HEIGHT -------------------------------------------------------------------------------- -- Reading and writing image pixels -- | Fill the given rectangle inside the image with the current -- color setting from the @StateVar@ 'clearColor'. -- -- 'clearImage' corresponds to the OpenVG function @vgClearImage@. -- clearImage :: VGImage -> Position -> Size -> IO () clearImage handle (Position x y) = unSizeM $ vgClearImage handle x y -- | Read the pixel values from memory and store the results in -- a rectagular portion of an image. -- -- 'imageSubData' corresponds to the OpenVG function -- @vgImageSubData@. -- imageSubData :: VGImage -> PixelData a -> Position -> Size -> IO () imageSubData image pd (Position x y) = unSizeM $ withPixelData pd $ \format_enum stride pixel_data -> vgImageSubData image pixel_data stride format_enum x y -- | Read the pixel values from a image and store the results in -- memory. -- -- 'getImageSubData' corresponds to the OpenVG function -- @vgGetImageSubData@. -- getImageSubData :: VGImage -> PixelData a -> Position -> Size -> IO () getImageSubData image pd (Position x y) = unSizeM $ withPixelData pd $ \format_enum stride pixel_data -> vgGetImageSubData image pixel_data stride format_enum x y -------------------------------------------------------------------------------- -- childImage - not implemented in shiva-vg -- getParent - not implemented in shiva-vg -------------------------------------------------------------------------------- -- Copying pixels between images -- | Copy pixels between images. -- -- 'copyImage' corresponds to the OpenVG function @vgCopyImage@. -- copyImage :: VGImage -> Position -> VGImage -> Position -> Size -> Bool -> IO () copyImage dst (Position dx dy) src (Position sx sy) sz dither = (unSizeM `flip` sz) $ \w h -> vgCopyImage dst dx dy src sx sy w h (marshalBool dither) -------------------------------------------------------------------------------- -- Drawing images to the drawing surface -- | Styles of image drawing data ImageMode = Normal | Multiply | Stencil deriving ( Eq, Ord, Show ) -- | Set the draw image mode. -- -- 'drawImageMode' is a write-only state variable corresponding to -- @VG_IMAGE_MODE@: -- -- > vgSeti(VG_IMAGE_MODE, quality); -- drawImageMode :: SettableStateVar ImageMode drawImageMode = makeSettableStateVar $ seti ImageMode . fromIntegral . marshalImageMode -- | Draw the image on the current drawing surface. -- -- 'drawImage' corresponds to the OpenVG function @vgDrawImage@. -- drawImage :: VGImage -> IO () drawImage = vgDrawImage -------------------------------------------------------------------------------- -- Reading and writing drawing surface pixels -- | Copy pixel data from the image to the drawing surface. -- -- 'setPixels' corresponds to the OpenVG function @vgSetPixels@. -- setPixels :: Position -> VGImage -> Position -> Size -> IO () setPixels (Position dx dy) src (Position sx sy) = unSizeM $ vgSetPixels dx dy src sx sy -- | Copy pixels to the drawing surface without first creating an -- image. -- -- 'writePixels' corresponds to the OpenVG function @vgWritePixels@. -- writePixels :: PixelData a -> Position -> Size -> IO () writePixels pd (Position dx dy) = unSizeM $ withPixelData pd $ \format_enum stride pixel_data -> vgWritePixels pixel_data stride format_enum dx dy -- | Retrieve pixel information from the drawing surface. -- -- 'getPixels' corresponds to the OpenVG function @vgGetPixels@. -- getPixels :: VGImage -> Position -> Position -> Size -> IO () getPixels dst (Position dx dy) (Position sx sy) = unSizeM $ vgGetPixels dst dx dy sx sy -- | Copy data from the drawing surface without creating an -- image first. -- -- 'readPixels' corresponds to the OpenVG function @vgReadPixels@. -- readPixels :: PixelData a -> Position -> Size -> IO () readPixels pd (Position sx sy) = unSizeM $ withPixelData pd $ \format_enum stride pixel_data -> vgReadPixels pixel_data stride format_enum sx sy -------------------------------------------------------------------------------- -- Copying portions of the drawing surface -- | Copy pixels from one region of the drawing surface to -- another. -- -- 'copyPixels' corresponds to the OpenVG function @vgCopyPixels@. -- copyPixels :: Position -> Position -> Size -> IO () copyPixels (Position dx dy) (Position sx sy) = unSizeM $ vgCopyPixels dx dy sx sy -------------------------------------------------------------------------------- marshalImageFormat :: ImageFormat -> VGenum marshalImageFormat x = case x of SRGBX8888 -> vg_sRGBX_8888 SRGBA8888 -> vg_sRGBA_8888 SRGBA8888Pre -> vg_sRGBA_8888_PRE SRGB565 -> vg_sRGB_565 SRGBA5551 -> vg_sRGBA_5551 SRGBA4444 -> vg_sRGBA_4444 SL8 -> vg_sL_8 LRGBX8888 -> vg_lRGBX_8888 LRGBA8888 -> vg_lRGBA_8888 LRGBA8888Pre -> vg_lRGBA_8888_PRE LL8 -> vg_lL_8 A8 -> vg_A_8 BW1 -> vg_BW_1 -- FormatA1 -> (not supported in shiva-vg) -- FormatA4 -> (not supported in shiva-vg) SXRGB8888 -> vg_sXRGB_8888 SARGB8888 -> vg_sARGB_8888 SARGB8888Pre -> vg_sARGB_8888_PRE SARGB1555 -> vg_sARGB_1555 SARGB4444 -> vg_sARGB_4444 LXRGB8888 -> vg_lXRGB_8888 LARGB8888 -> vg_lARGB_8888 LARGB8888Pre -> vg_lARGB_8888_PRE SBGRX8888 -> vg_sBGRX_8888 SBGRA8888 -> vg_sBGRA_8888 SBGRA8888Pre -> vg_sBGRA_8888_PRE SBGR565 -> vg_sBGR_565 SBGRA5551 -> vg_sBGRA_5551 SBGRA4444 -> vg_sBGRA_4444 LBGRX8888 -> vg_lBGRX_8888 LBGRA8888 -> vg_lBGRA_8888 LBGRA8888Pre -> vg_lBGRA_8888_PRE SXBGR8888 -> vg_sXBGR_8888 SABGR8888 -> vg_sABGR_8888 SABGR8888Pre -> vg_sABGR_8888_PRE SABGR1555 -> vg_sABGR_1555 SABGR4444 -> vg_sABGR_4444 LXBGR8888 -> vg_lXBGR_8888 LABGR8888 -> vg_lABGR_8888 LABGR8888Pre -> vg_lABGR_8888_PRE unmarshalImageFormat :: VGenum -> ImageFormat unmarshalImageFormat x | x == vg_sRGBX_8888 = SRGBX8888 | x == vg_sRGBA_8888 = SRGBA8888 | x == vg_sRGBA_8888_PRE = SRGBA8888Pre | x == vg_sRGB_565 = SRGB565 | x == vg_sRGBA_5551 = SRGBA5551 | x == vg_sRGBA_4444 = SRGBA4444 | x == vg_sL_8 = SL8 | x == vg_lRGBX_8888 = LRGBX8888 | x == vg_lRGBA_8888 = LRGBA8888 | x == vg_lRGBA_8888_PRE = LRGBA8888Pre | x == vg_lL_8 = LL8 | x == vg_A_8 = A8 | x == vg_BW_1 = BW1 -- FormatA1 = (not supported in shiva-vg) -- FormatA4 = (not supported in shiva-vg) | x == vg_sXRGB_8888 = SXRGB8888 | x == vg_sARGB_8888 = SARGB8888 | x == vg_sARGB_8888_PRE = SARGB8888Pre | x == vg_sARGB_1555 = SARGB1555 | x == vg_sARGB_4444 = SARGB4444 | x == vg_lXRGB_8888 = LXRGB8888 | x == vg_lARGB_8888 = LARGB8888 | x == vg_lARGB_8888_PRE = LARGB8888Pre | x == vg_sBGRX_8888 = SBGRX8888 | x == vg_sBGRA_8888 = SBGRA8888 | x == vg_sBGRA_8888_PRE = SBGRA8888Pre | x == vg_sBGR_565 = SBGR565 | x == vg_sBGRA_5551 = SBGRA5551 | x == vg_sBGRA_4444 = SBGRA4444 | x == vg_lBGRX_8888 = LBGRX8888 | x == vg_lBGRA_8888 = LBGRA8888 | x == vg_lBGRA_8888_PRE = LBGRA8888Pre | x == vg_sXBGR_8888 = SXBGR8888 | x == vg_sABGR_8888 = SABGR8888 | x == vg_sABGR_8888_PRE = SABGR8888Pre | x == vg_sABGR_1555 = SABGR1555 | x == vg_sABGR_4444 = SABGR4444 | x == vg_lXBGR_8888 = LXBGR8888 | x == vg_lABGR_8888 = LABGR8888 | x == vg_lABGR_8888_PRE = LABGR8888Pre | otherwise = error ("unmarshalImageFormat: illegal value " ++ show x) marshalImageQuality :: ImageQuality -> VGenum marshalImageQuality x = case x of Nonantialiased -> vg_IMAGE_QUALITY_NONANTIALIASED Faster -> vg_IMAGE_QUALITY_FASTER Better -> vg_IMAGE_QUALITY_BETTER marshalImageMode :: ImageMode -> VGenum marshalImageMode x = case x of Normal -> vg_DRAW_IMAGE_NORMAL Multiply -> vg_DRAW_IMAGE_MULTIPLY Stencil -> vg_DRAW_IMAGE_STENCIL