packages feed

bmp 1.2.3.2 → 1.2.3.3

raw patch · 10 files changed

+158/−80 lines, 10 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

+ Codec.BMP: dib3HeightFlipped :: BitmapInfoV3 -> Bool
- Codec.BMP: BitmapInfoV3 :: Word32 -> Word32 -> Word32 -> Word16 -> Word16 -> Compression -> Word32 -> Word32 -> Word32 -> Word32 -> Word32 -> BitmapInfoV3
+ Codec.BMP: BitmapInfoV3 :: Word32 -> Word32 -> Word32 -> Bool -> Word16 -> Word16 -> Compression -> Word32 -> Word32 -> Word32 -> Word32 -> Word32 -> BitmapInfoV3

Files

Codec/BMP/BitmapInfo.hs view
@@ -9,7 +9,7 @@ import Data.Binary import Data.Binary.Get --- Image Headers --------------------------------------------------------------+ -- | A wrapper for the various image header types. --    data BitmapInfo
Codec/BMP/BitmapInfoV3.hs view
@@ -12,8 +12,10 @@ import Data.Binary import Data.Binary.Get	 import Data.Binary.Put+import Data.Int import Debug.Trace + -- | Device Independent Bitmap (DIB) header for Windows V3. data BitmapInfoV3 	= BitmapInfoV3			@@ -26,6 +28,10 @@ 	  -- | (+8) Height of the image, in pixels. 	, dib3Height		:: Word32 	+          -- | If the height field in the file is negative then this is interpreted+          --   as an image with the rows flipped.+        , dib3HeightFlipped     :: Bool+ 	  -- | (+12) Number of color planes. 	, dib3Planes		:: Word16 @@ -65,9 +71,19 @@  instance Binary BitmapInfoV3 where  get-  = do	size	<- getWord32le-	width	<- getWord32le-	height	<- getWord32le+  = do	size	  <- getWord32le+	width	  <- getWord32le++        -- We're supposed to treat the height field as a signed integer.+        -- If it's negative it means the image is flipped along the X axis.+        -- (which is crazy, but we just have to eat it)+	heightW32 <- getWord32le+        let heightI32 = (fromIntegral heightW32 :: Int32)+        let (height, flipped)+                = if heightI32 < 0+                        then (fromIntegral (abs heightI32), True)+                        else (heightW32,                      False)+ 	planes	<- getWord16le 	bitc	<- getWord16le 	comp	<- get@@ -81,6 +97,7 @@ 		{ dib3Size		= size 		, dib3Width		= width 		, dib3Height		= height+                , dib3HeightFlipped     = flipped 		, dib3Planes		= planes 		, dib3BitCount		= bitc 		, dib3Compression	= comp@@ -132,7 +149,8 @@         --  in the header, because some encoders add padding to the end.         | Just calculatedImageSize      <- imageSizeFromBitmapInfoV3 header         , fromIntegral physicalBufferSize < calculatedImageSize-        = Just  $ ErrorImageDataTruncated +        = trace (show header)+        $ Just  $ ErrorImageDataTruncated                          calculatedImageSize                         (fromIntegral physicalBufferSize) 
Codec/BMP/BitmapInfoV4.hs view
@@ -14,6 +14,7 @@ import Data.Binary.Get	 import Data.Binary.Put + -- | Device Independent Bitmap (DIB) header for Windows V4 (95 and newer) data BitmapInfoV4 	= BitmapInfoV4@@ -126,7 +127,6 @@   	-- Check for valid compression modes -----         -- uncompressed 32bit RGBA stated as CompressionRGB.         | dib3BitCount    headerV3 == 32         , dib3Compression headerV3 == CompressionRGB@@ -191,3 +191,4 @@         = Nothing          where   headerV3 = dib4InfoV3 headerV4+
Codec/BMP/CIEXYZ.hs view
@@ -7,6 +7,7 @@ import Data.Binary.Get import Data.Binary.Put  + -- | Contains the XYZ coordinates of a specific color in a specified color --   space. data CIEXYZ 
Codec/BMP/Compression.hs view
@@ -8,6 +8,7 @@ import Data.Binary.Put  +-- | The Compression mode says how the image data is encoded in the file. data Compression         = CompressionRGB         | CompressionRLE8
Codec/BMP/Error.hs view
@@ -5,9 +5,9 @@ import Codec.BMP.Compression import Data.Word + -- | Things that can go wrong when loading a BMP file. data Error-         -- | Magic number was not at the start of the file,          --   so this probably isn't a BMP file.         = ErrorBadMagic
Codec/BMP/FileHeader.hs view
@@ -12,7 +12,6 @@ import Data.Binary.Put  --- File Headers --------------------------------------------------------------- -- | BMP file header. data FileHeader 	= FileHeader			@@ -33,9 +32,11 @@ 	} 	deriving (Show) + -- | Size of a file header (in bytes). sizeOfFileHeader :: Int sizeOfFileHeader = 14+  -- | Magic number that should come at the start of a BMP file. bmpMagic :: Word16
Codec/BMP/Pack.hs view
@@ -17,20 +17,32 @@ import Data.ByteString.Unsafe	as BS import Prelude			as P + -- | Pack a string of RGBA component values into a BMP image.---	If the given dimensions don't match the input string then `error`.---	This currently ignores the alpha component of the input string and---      produces a 24bit RGB image.+--+--  * If the given dimensions don't match the input string then `error`.+--+--  * If the width or height fields are negative then `error`.+--+--  * This currently ignores the alpha component of the input string and+--    produces a 24bit RGB image.+-- packRGBA32ToBMP-	:: Int 		-- ^ Width of image.-	-> Int 		-- ^ Height of image.+	:: Int 		-- ^ Width of image  (must be positive).+	-> Int 		-- ^ Height of image (must be positive). 	-> ByteString	-- ^ A string of RGBA component values.                         --   Must have length (@width * height * 4@) 	-> BMP 	 packRGBA32ToBMP width height str+ | width < 0+ = error "Codec.BMP: Negative width field."++ | height < 0+ = error "Codec.BMP: Negative height field."+  | height * width * 4 /= BS.length str- = error "Codec.BMP.packRGBAToBMP: given image dimensions don't match input data."+ = error "Codec.BMP: Image dimensions don't match input data."   | otherwise  = let	(imageData, _)	= packRGBA32ToRGB24 width height str@@ -39,18 +51,22 @@ 		= FileHeader 		{ fileHeaderType	= bmpMagic -		, fileHeaderFileSize	= fromIntegral-					$ sizeOfFileHeader + sizeOfBitmapInfoV3	+ BS.length imageData+		, fileHeaderFileSize	+                        = fromIntegral+			$ sizeOfFileHeader + sizeOfBitmapInfoV3	+                                           + BS.length imageData  		, fileHeaderReserved1	= 0 		, fileHeaderReserved2	= 0-		, fileHeaderOffset	= fromIntegral (sizeOfFileHeader + sizeOfBitmapInfoV3) }+		, fileHeaderOffset	+                        = fromIntegral (sizeOfFileHeader + sizeOfBitmapInfoV3)}  	bitmapInfoV3 		= BitmapInfoV3 		{ dib3Size		= fromIntegral sizeOfBitmapInfoV3 		, dib3Width		= fromIntegral width 		, dib3Height		= fromIntegral height+                , dib3HeightFlipped     = False 		, dib3Planes		= 1 		, dib3BitCount		= 24 		, dib3Compression	= CompressionRGB@@ -65,9 +81,12 @@ 		, dib3ColorsUsed	= 0 		, dib3ColorsImportant	= 0 } 		+        -- We might as well check to see if we've made a well-formed BMP file.+        -- It would be sad if we couldn't read a file we just wrote. 	errs	= catMaybes		 			[ checkFileHeader   fileHeader-			, checkBitmapInfoV3 bitmapInfoV3 (fromIntegral $ BS.length imageData)]+			, checkBitmapInfoV3 bitmapInfoV3 +                                           (fromIntegral $ BS.length imageData)] 		    in	case errs of 	 [] -> BMP @@ -75,19 +94,21 @@ 		, bmpBitmapInfo		= InfoV3 bitmapInfoV3 		, bmpRawImageData	= imageData } 	 -	 _  -> error $ "Codec.BMP: packRGBA32ToBMP constructed BMP file has errors, sorry.\n" ++ show errs+	 _  -> error $ "Codec.BMP: Constructed BMP file has errors, sorry." +                     ++ show errs    packRGBA32ToRGB24 -	:: Int			-- ^ Width of image.-	-> Int			-- ^ Height of image.-	-> ByteString-	-> (ByteString, Int)	-- output bytestring, and number of pad bytes per line.+	:: Int		       -- ^ Width of image.+	-> Int		       -- ^ Height of image.+	-> ByteString          -- ^ Source bytestring holding the image data. +	-> (ByteString, Int)   -- output bytestring, and number of pad+                               -- bytes per line. 	 packRGBA32ToRGB24 width height str  | height * width * 4 /= BS.length str- = error "Codec.BMP.packRGBAToRGB24: given image dimensions don't match input data."+ = error "Codec.BMP: Image dimensions don't match input data."   | otherwise  = let	padPerLine	@@ -122,9 +143,8 @@ 	 	 -- process a pixel 	 | otherwise-	 = do	-		red	:: Word8  <- peekByteOff ptrSrc (oSrc + 0)-		green	:: Word8  <- peekByteOff ptrSrc (oSrc + 1)+	 = do   red	:: Word8  <- peekByteOff ptrSrc (oSrc + 0)+                green	:: Word8  <- peekByteOff ptrSrc (oSrc + 1) 		blue	:: Word8  <- peekByteOff ptrSrc (oSrc + 2) 	 		pokeByteOff ptrDest (oDest + 0) blue@@ -132,5 +152,4 @@ 		pokeByteOff ptrDest (oDest + 2) red 		 		go (posX + 1) posY (oSrc + 4) (oDest + 3)- 
Codec/BMP/Unpack.hs view
@@ -22,11 +22,12 @@  = let	info		= getBitmapInfoV3 $ bmpBitmapInfo bmp 	width		= fromIntegral $ dib3Width  info 	height		= fromIntegral $ dib3Height info+        flipX           = dib3HeightFlipped info 	bitCount	= dib3BitCount info    in	case bitCount of-	 24	-> packRGB24ToRGBA32 width height (bmpRawImageData bmp)-	 32	-> packRGB32ToRGBA32 width height (bmpRawImageData bmp)-	 _	-> error "Codec.BMP.unpackBMPToRGBA32: unhandled bitcount."+	 24	-> packRGB24ToRGBA32 width height flipX (bmpRawImageData bmp)+	 32	-> packRGB32ToRGBA32 width height flipX (bmpRawImageData bmp)+	 _	-> error "Codec.BMP: Unhandled bitcount."   -- | Unpack raw, uncompressed 24 bit BMP image data to a string of@@ -34,53 +35,70 @@ -- --   The alpha component is set to 255 for every pixel. packRGB24ToRGBA32-	:: Int 			-- Width of image.-	-> Int			-- Height of image.-	-> ByteString 		-- Input string.+	:: Int 			-- ^ Width of image.+	-> Int			-- ^ Height of image.+        -> Bool                 -- ^ Image data is flipped along the X axis.+	-> ByteString 		-- ^ Input string. 	-> ByteString 		-packRGB24ToRGBA32 width height str- = let	bytesPerLine	= BS.length str `div` height-	padPerLine	= bytesPerLine - width * 3+packRGB24ToRGBA32 width height flipX str+ = let	-- Number of bytes per line in the source file, +        -- including padding bytes.+        srcBytesPerLine	= BS.length str `div` height 	sizeDest	= width * height * 4          -- We allow padding bytes on the end of the image data.-   in	if BS.length str < height * (width * 3 + padPerLine)-	 then error "Codec.BMP.unpackRGB24ToRGBA32: image data is truncated."+   in	if BS.length str < height * srcBytesPerLine+	 then error "Codec.BMP: Image data is truncated."  	 else unsafePerformIO        	 	$ allocaBytes sizeDest      $ \bufDest ->     	   	  BS.unsafeUseAsCString str $ \bufSrc  ->-            	   do	packRGB24ToRGBA32' width height padPerLine+            	   do	packRGB24ToRGBA32' +                                width height flipX +                                srcBytesPerLine                                 (castPtr bufSrc) (castPtr bufDest) 			packCStringLen (bufDest, sizeDest)  		 -- We're doing this via Ptrs because we don't want to take the -- overhead of doing the bounds checks in ByteString.index.-packRGB24ToRGBA32' width height pad ptrSrc ptrDest - = go 0 0 0 0+packRGB24ToRGBA32' width height flipX srcBytesPerLine ptrSrc ptrDst + = go 0  where	-	go posX posY oSrc oDest-	 -- skip over padding bytes at the end of each line.+        go posY+         -- we've finished the image.+         | posY == height+         = return ()++         -- Image source data is flipped along the X axis.+         | flipX+         = let  !oSrc   = srcBytesPerLine * (height - 1 - posY)+                !oDst   = width * 4 * posY+           in   go_line 0 posY oSrc oDst++         -- Image source data is in the natural order.+         | otherwise+         = let  !oSrc   = srcBytesPerLine * posY+                !oDst   = width * 4 * posY+           in   go_line 0 posY oSrc oDst++	go_line posX posY oSrc oDst+	 -- move to the next line. 	 | posX == width -	 = go 0 (posY + 1) (oSrc + pad) oDest-	-	 -- we've finished the image.-	 | posY == height-	 = return ()-	+	 = go (posY + 1)+		 	 -- process a pixel. 	 | otherwise 	 = do	blue  :: Word8	<- peekByteOff ptrSrc (oSrc + 0) 		green :: Word8	<- peekByteOff ptrSrc (oSrc + 1) 		red   :: Word8	<- peekByteOff ptrSrc (oSrc + 2) -		pokeByteOff ptrDest (oDest + 0) red-		pokeByteOff ptrDest (oDest + 1) green-		pokeByteOff ptrDest (oDest + 2) blue-		pokeByteOff ptrDest (oDest + 3) (255 :: Word8)+		pokeByteOff ptrDst (oDst + 0) red+		pokeByteOff ptrDst (oDst + 1) green+		pokeByteOff ptrDst (oDst + 2) blue+		pokeByteOff ptrDst (oDst + 3) (255 :: Word8) 		-		go (posX + 1) posY (oSrc + 3) (oDest + 4)+		go_line (posX + 1) posY (oSrc + 3) (oDst + 4)   @@ -89,35 +107,50 @@ --   Note in the BMP file the components are arse-around ABGR instead of RGBA.  --   The 'unpacking' here is really just flipping the components around. packRGB32ToRGBA32-	:: Int 			-- Width of image.-	-> Int			-- Height of image.-	-> ByteString 		-- Input string.+	:: Int 			-- ^ Width of image.+	-> Int			-- ^ Height of image.+        -> Bool                 -- ^ Image data is flipped along the X axis.+	-> ByteString 		-- ^ Input string. 	-> ByteString 		-packRGB32ToRGBA32 width height str+packRGB32ToRGBA32 width height flipX str   = let sizeDest = height * width * 4     in  if  BS.length str < sizeDest-	 then error "Codec.BMP.packRGB24ToRGBA32: image data is truncated."+	 then error "Codec.BMP: Image data is truncated."  	 else unsafePerformIO        	 	$ allocaBytes sizeDest      $ \bufDest ->     	   	  BS.unsafeUseAsCString str $ \bufSrc  ->             	   do	packRGB32ToRGBA32' width height+                                flipX                                 (castPtr bufSrc) (castPtr bufDest) 			packCStringLen (bufDest, sizeDest) 		 -- We're doing this via Ptrs because we don't want to take the -- overhead of doing the bounds checks in ByteString.index.-packRGB32ToRGBA32' width height ptrSrc ptrDest - = go 0 0 0 0+packRGB32ToRGBA32' width height flipX ptrSrc ptrDst+ = go 0  where	-	go posX posY oSrc oDest-	 -- skip over padding bytes at the end of each line.-	 | posX == width -	 = go 0 (posY + 1) oSrc oDest+	go posY+         -- we've finished the image.+         | posY == height+         = return ()++         -- Image source data is flipped along the X axis.+         | flipX+         = let  !oSrc   = width * 4 * (height - 1 - posY)+                !oDst   = width * 4 * posY+           in   go_line 0 posY oSrc oDst 	-	 -- we've finished the image.-	 | posY == height-	 = return ()+         -- Image source data is in the natural order.+         | otherwise+         = let  !oSrc   = width * 4 * posY+                !oDst   = width * 4 * posY+           in   go_line 0 posY oSrc oDst++        go_line posX posY oSrc oDst+         -- move to the next line.+         | posX == width +         = go (posY + 1) 	 	 -- process a pixel. 	 | otherwise@@ -126,10 +159,10 @@ 		red    :: Word8	<- peekByteOff ptrSrc (oSrc + 2) 		alpha  :: Word8 <- peekByteOff ptrSrc (oSrc + 3) -		pokeByteOff ptrDest (oDest + 0) red-		pokeByteOff ptrDest (oDest + 1) green-		pokeByteOff ptrDest (oDest + 2) blue-		pokeByteOff ptrDest (oDest + 3) alpha+		pokeByteOff ptrDst (oDst + 0) red+		pokeByteOff ptrDst (oDst + 1) green+		pokeByteOff ptrDst (oDst + 2) blue+		pokeByteOff ptrDst (oDst + 3) alpha 		-		go (posX + 1) posY (oSrc + 4) (oDest + 4)+		go_line (posX + 1) posY (oSrc + 4) (oDst + 4) 
bmp.cabal view
@@ -1,5 +1,5 @@ Name:                bmp-Version:             1.2.3.2+Version:             1.2.3.3 License:             MIT License-file:        LICENSE Author:              Ben Lippmeier@@ -12,14 +12,15 @@ Bug-reports:         bmp@ouroborus.net Description: 	Read and write uncompressed BMP image files. 100% robust Haskell implementation.- Synopsis:         Read and write uncompressed BMP image files. -Tested-with: GHC == 7.2+source-repository head+        type:           darcs+        location:       http://code.ouroborus.net/bmp-head  Library-  Build-Depends: +  build-Depends:          base                 == 4.*,         bytestring           == 0.10.*,         binary               == 0.5.*@@ -27,10 +28,13 @@   ghc-options:         -Wall -fno-warn-missing-signatures -  Exposed-modules:+  extensions:+        BangPatterns++  exposed-modules:         Codec.BMP -  Other-modules:+  other-modules:         Codec.BMP.Base         Codec.BMP.Compression         Codec.BMP.BitmapInfo