{-# OPTIONS_HADDOCK hide #-}
module Codec.BMP.FileHeader
	( FileHeader	(..)
	, bmpMagic
	, sizeOfFileHeader
	, checkFileHeader)
where
import Codec.BMP.BitmapInfoV3
import Codec.BMP.Error
import Data.Binary
import Data.Binary.Get	
import Data.Binary.Put


-- | BMP file header.
data FileHeader
	= FileHeader			
	{ -- | (+0) Magic numbers 0x42 0x4d
	  fileHeaderType	:: Word16
	
	  -- | (+2) Size of the file, in bytes.
	, fileHeaderFileSize	:: Word32

	  -- | (+6) Reserved, must be zero.
	, fileHeaderReserved1	:: Word16

	  -- | (+8) Reserved, must be zero.
	, fileHeaderReserved2	:: Word16

	  -- | (+10) Offset in bytes to the start of the pixel data.
	, fileHeaderOffset	:: Word32
	}
	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
bmpMagic = 0x4d42


instance Binary FileHeader where
 get 
  = do	t	<- getWord16le
	size	<- getWord32le
	res1	<- getWord16le
	res2	<- getWord16le
	offset	<- getWord32le
	
	return	$ FileHeader
		{ fileHeaderType	= t
		, fileHeaderFileSize	= size
		, fileHeaderReserved1	= res1
		, fileHeaderReserved2   = res2
		, fileHeaderOffset	= offset }

 put header
  = do	putWord16le	$ fileHeaderType header
	putWord32le	$ fileHeaderFileSize header
	putWord16le	$ fileHeaderReserved1 header
	putWord16le	$ fileHeaderReserved2 header
	putWord32le	$ fileHeaderOffset header
	

-- | Check a file header for problems and unsupported features.
checkFileHeader :: FileHeader -> Maybe Error	
checkFileHeader header
	| fileHeaderType header /= bmpMagic
	= Just	$ ErrorBadMagic (fileHeaderType header)

        | fileHeaderFileSize header 
                < fromIntegral sizeOfFileHeader
        = Just  $ ErrorFileHeaderTruncated

        | fileHeaderFileSize header 
                < fromIntegral (sizeOfFileHeader + sizeOfBitmapInfoV3)
        = Just  $ ErrorImageHeaderTruncated

	| fileHeaderReserved1 header /= 0
	= Just 	$ ErrorReservedFieldNotZero

	| fileHeaderReserved2 header /= 0
	= Just 	$ ErrorReservedFieldNotZero

	| fromIntegral (fileHeaderOffset header) 
                /= sizeOfFileHeader + sizeOfBitmapInfoV3
	= Just	$ ErrorDodgyFileHeaderFieldOffset
		$ fromIntegral $ fileHeaderOffset header

	| otherwise
	= Nothing
