{-# LANGUAGE PatternGuards #-}{-# OPTIONS_HADDOCK hide #-}moduleCodec.BMP.BitmapInfoV3(BitmapInfoV3(..),Compression(..),sizeOfBitmapInfoV3,checkBitmapInfoV3,imageSizeFromBitmapInfoV3)whereimportCodec.BMP.ErrorimportCodec.BMP.CompressionimportData.BinaryimportData.Binary.GetimportData.Binary.PutimportDebug.Trace-- | Device Independent Bitmap (DIB) header for Windows V3.dataBitmapInfoV3=BitmapInfoV3{-- | (+0) Size of the image header, in bytes.dib3Size::Word32-- | (+4) Width of the image, in pixels.,dib3Width::Word32-- | (+8) Height of the image, in pixels.,dib3Height::Word32-- | (+12) Number of color planes.,dib3Planes::Word16-- | (+14) Number of bits per pixel.,dib3BitCount::Word16-- | (+16) Image compression mode.,dib3Compression::Compression-- | (+20) Size of raw image data.-- Some encoders set this to zero, so we need to calculate it based-- on the overall file size.-- -- If it is non-zero then we check it matches the file size - header-- size.,dib3ImageSize::Word32-- | (+24) Prefered resolution in pixels per meter, along the X axis.,dib3PelsPerMeterX::Word32-- | (+28) Prefered resolution in pixels per meter, along the Y axis.,dib3PelsPerMeterY::Word32-- | (+32) Number of color entries that are used.,dib3ColorsUsed::Word32-- | (+36) Number of significant colors.,dib3ColorsImportant::Word32}deriving(Show)-- | Size of `BitmapInfoV3` header (in bytes)sizeOfBitmapInfoV3::IntsizeOfBitmapInfoV3=40instanceBinaryBitmapInfoV3whereget=dosize<-getWord32lewidth<-getWord32leheight<-getWord32leplanes<-getWord16lebitc<-getWord16lecomp<-getimgsize<-getWord32lepelsX<-getWord32lepelsY<-getWord32lecused<-getWord32lecimp<-getWord32lereturn$BitmapInfoV3{dib3Size=size,dib3Width=width,dib3Height=height,dib3Planes=planes,dib3BitCount=bitc,dib3Compression=comp,dib3ImageSize=imgsize,dib3PelsPerMeterX=pelsX,dib3PelsPerMeterY=pelsY,dib3ColorsUsed=cused,dib3ColorsImportant=cimp}putheader=doputWord32le$dib3SizeheaderputWord32le$dib3WidthheaderputWord32le$dib3HeightheaderputWord16le$dib3PlanesheaderputWord16le$dib3BitCountheaderput$dib3CompressionheaderputWord32le$dib3ImageSizeheaderputWord32le$dib3PelsPerMeterXheaderputWord32le$dib3PelsPerMeterYheaderputWord32le$dib3ColorsUsedheaderputWord32le$dib3ColorsImportantheader-- | Check headers for problems and unsupported features. checkBitmapInfoV3::BitmapInfoV3->Word32->MaybeErrorcheckBitmapInfoV3headerphysicalBufferSize-- We only handle a single color plane.|dib3Planesheader/=1=Just$ErrorUnhandledPlanesCount$dib3Planesheader-- We only handle 24 and 32 bit images.|dib3BitCountheader/=24,dib3BitCountheader/=32=Just$ErrorUnhandledColorDepth$dib3BitCountheader-- If the image size field in the header is non-zero, -- then it must be less than the physical size of the image buffer.-- The buffer may be larger than the size of the image stated-- in the header, because some encoders add padding to the end.|headerImageSize<-dib3ImageSizeheader,headerImageSize/=0,physicalBufferSize<headerImageSize=Just$ErrorImagePhysicalSizeMismatchheaderImageSizephysicalBufferSize-- Check that the physical buffer contains enough image data.-- The buffer may be larger than the size of the image stated-- in the header, because some encoders add padding to the end.|JustcalculatedImageSize<-imageSizeFromBitmapInfoV3header,fromIntegralphysicalBufferSize<calculatedImageSize=Just$ErrorImageDataTruncatedcalculatedImageSize(fromIntegralphysicalBufferSize)-- We only handle uncompresssed images.|dib3Compressionheader/=CompressionRGB&&dib3Compressionheader/=CompressionBitFields=Just$ErrorUnhandledCompressionMode(dib3Compressionheader)|otherwise=Nothing-- | Compute the size of the image data from the header.---- * We can't just use the 'dib3ImageSize' field because some encoders-- set this to zero.---- * We also can't use the physical size of the data in the file because-- some encoders add zero padding bytes on the end. --imageSizeFromBitmapInfoV3::BitmapInfoV3->MaybeIntimageSizeFromBitmapInfoV3header|dib3BitCountheader==32,dib3Planesheader==1,dib3Compressionheader==CompressionRGB||dib3Compressionheader==CompressionBitFields=Just$fromIntegral(dib3Widthheader*dib3Heightheader*4)|dib3BitCountheader==24,dib3Planesheader==1,dib3Compressionheader==CompressionRGB||dib3Compressionheader==CompressionBitFields=letimageBytesPerLine=dib3Widthheader*3tailBytesPerLine=imageBytesPerLine`mod`4padBytesPerLine=iftailBytesPerLine>0then4-tailBytesPerLineelse0inJust$fromIntegral$dib3Heightheader*imageBytesPerLine+padBytesPerLine|otherwise=trace(showheader)$Nothing