[HOpenGL] bitmap loader

Andre W B Furtado awfurtado@uol.com.br
Tue, 23 Oct 2001 03:41:40 -0200


This is a multi-part message in MIME format.

------=_NextPart_000_0005_01C15B74.A0715380
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

Hello everybody. I'm developing a HOpenGL bitmap loader, and what I've done
so far is a 24-bit bitmap loader that is taking more seconds than expected
to load a medium sized bitmap. It also makes the heap exhausted if the size
of the file is greater than 900k +/-. At least, it works. Use function

loadBitmap :: FilePath -> Maybe InvisibleColorList -> IO AwbfBitmap

to load a 24-bit bitmap and

loadBitmapList :: [(FilePath, Maybe InvisibleColorList)] -> IO [AwbfBitmap]

to load multiple 24-bit bitmaps.

I'm sending the code to you. Feel free to modify the file and perhaps figure
out the solution for the delay problem....

Cheers,
-- Andre

------=_NextPart_000_0005_01C15B74.A0715380
Content-Type: application/octet-stream;
	name="Awbfbmp.hs"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="Awbfbmp.hs"

{-

24-bit Bitmap Loader (v3)
by Andre W B Furtado
awfurtado@uol.com.br

This program is intended to be used with HOpenGL only.
Check the AWBF HOpenGL Tutorial at:
www.cin.ufpe.br/~haskell/hopengl/

-}

module Awbfbmp where

import GL
import IO
import IOExts
import Monad(liftM)

------ Start of Bitmap Code -------

binAux :: String
binAux =3D "000000000000000000000000"

type AwbfBitmap =3D (GLsizei, GLsizei, PixelDescriptor)
type BmpList =3D [(GLubyte, GLubyte, GLubyte, GLubyte)]
type InvisibleColorList =3D [(GLubyte, GLubyte, GLubyte)]

--loads a bitmap from a file
loadBitmap :: FilePath -> Maybe InvisibleColorList -> IO AwbfBitmap
loadBitmap bmName invList =3D do
	bmFile <- openFileEx bmName (BinaryMode ReadMode)
	bmString <- hGetContents bmFile
	(bmW,bmH) <- getWH (myDrop 18 bmString)
	bmData <- getBmData (myDrop 54 bmString) (bmW,bmH) invList
	hClose bmFile            =20
	return (bmW,bmH,bmData)

 -- loads n bitmaps from n files=09
loadBitmapList :: [(FilePath, Maybe InvisibleColorList)] -> IO =
[AwbfBitmap]
loadBitmapList bmps =3D do
	bmList <- loadBmListAux bmps []
	return (reverse bmList)

loadBmListAux :: [(FilePath, Maybe InvisibleColorList)] -> [AwbfBitmap] =
-> IO [AwbfBitmap]
loadBmListAux [] bmList =3D return (bmList)
loadBmListAux ((n,l):as) bmList =3D do
	bm <- loadBitmap n l
	loadBmListAux as (bm:bmList)

getWH :: String -> IO (GLsizei,GLsizei)
getWH (a:b:c:d:e:f:g:h:_) =3D do
	return ( (op (bin a) 0) + (op (bin b) 8) + (op (bin c) 16) + (op (bin =
d) 24),
	         (op (bin e) 0) + (op (bin f) 8) + (op (bin g) 16) + (op (bin =
h) 24))
 	         where bin x =3D toBinary(ord x)
	               op x n =3D toDecimal(shiftLeft(binAux ++ (make0 (8 - =
(length x)) ++ x)) n)
getWH _ =3D error "Awbfbmp.getWH error: strange bitmap file"	            =
 =20

getBmData :: String -> (GLsizei,GLsizei) -> Maybe InvisibleColorList -> =
IO PixelDescriptor
getBmData bmString (bmW,bmH) invList =3D do
	colorList <- makeColorListIO bmString (bmW,bmH)
	bmData <- liftM (PixelDescriptor GL.Rgba UnsignedByte . snd) . =
marshalList $
                   [Color4 r g b a | (r,g,b,a) <- addInvisiblity =
colorList invList]
       	return (bmData)
       =09
addInvisiblity :: [(GLubyte, GLubyte, GLubyte)] -> Maybe =
InvisibleColorList -> BmpList
addInvisiblity [] _ =3D []
addInvisiblity ((r,g,b):as) Nothing =3D ((r,g,b,255):(addInvisiblity as =
Nothing))
addInvisiblity ((r,g,b):as) l@(Just invList) | (r,g,b) `elem` invList =
=3D ((r,g,b,0):(addInvisiblity as l))
     			    		     | otherwise =3D ((r,g,b,255):(addInvisiblity as l))
     			    		    =20
makeColorListIO :: String -> (GLsizei,GLsizei) -> IO [(GLubyte, GLubyte, =
GLubyte)]
makeColorListIO bmString (bmW,bmH) =3D return (makeColorList x bmString =
(bmW*bmH) (bmW,bmW))
				     where x =3D (bmW `mod` 4)
		=09
makeColorList :: GLsizei -> String -> GLsizei -> (GLsizei,GLsizei) -> =
[(GLubyte, GLubyte, GLubyte)]
makeColorList _ _ 0 _ =3D []
makeColorList x bmString totVert (0,bmW) =3D makeColorList x (myDrop x =
bmString) totVert (bmW,bmW)
makeColorList x (b:g:r:bmString) totVert (n,bmW) =3D (ord2 r,ord2 g,ord2 =
b): (makeColorList x bmString (totVert - 1) (n - 1,bmW))
makeColorList _ _ _ _ =3D error "Awbfbmp.makeColorList error: strange =
bitmap file"

shiftLeft :: String -> Int -> String
shiftLeft a 0 =3D a
shiftLeft (_:as) n =3D shiftLeft(as ++ "0") (n-1)
shiftLeft _ _ =3D []

toDecimal :: String -> GLsizei
toDecimal a =3D toDecimalAux (reverse a) 32

toDecimalAux :: String -> GLsizei -> GLsizei
toDecimalAux [] _ =3D 0
toDecimalAux _ 0 =3D 0
toDecimalAux (a:as) n
		| a =3D=3D '0' =3D toDecimalAux as (n-1)
		| otherwise =3D pow2 (32 - n) + toDecimalAux as (n-1)
	=09
pow2 :: GLsizei -> GLsizei
pow2 0 =3D 1
pow2 n =3D 2 * pow2(n-1)

toBinary :: Int -> String
toBinary n
	| n < 2 =3D show n
	| otherwise =3D toBinary (n `div` 2) ++ (show (n `mod` 2))
=09
make0 :: Int -> String
make0 0 =3D []
make0 n =3D '0':(make0 (n-1))

to_Int :: GLsizei -> Integer
to_Int a =3D read (show a)

toGLsizei :: Integer -> GLsizei
toGLsizei a =3D read (show a)

integer2Int :: Integer -> Int
integer2Int a =3D read (show a)

ord2 :: Char -> GLubyte
ord2 a =3D read(show(ord a))

ord :: Char -> Int
ord =3D fromEnum

myDrop                :: GLsizei -> [a] -> [a]
myDrop 0 xs            =3D xs
myDrop _ []            =3D []
myDrop n (_:xs) | n>0  =3D myDrop (n-1) xs
myDrop _ _ =3D error "Awbfbmp.myDrop error: negative argument"

------=_NextPart_000_0005_01C15B74.A0715380--