Post by GuppyB on Apr 28, 2005 21:40:26 GMT -5
ok, first let me say, I know, I know, it's been a long time since I have posted a demo up. The demands of earning a living and raising a family have been steep. I finally got a little time outside of the rest of my life to work on Basic4GL. Getting back into Basic4GL, I wanted to do a demo related to reading from files because I hadn't done that yet so....
Most of you should see the relevance of being able to read BMP files into an array. The obvious example and the one I have included with this reader is for creating height maps based on the luminance of the pixel. This means if you wanted to create a 3D outdoor environment, you could do so in a BMP file in Photoshop and read the data in as opposed to writing a thousand "Data" statements.
This program will work on 24 bit BMPs and 8 bit BMPs in a Windows format with no compression. I got most of the information to create this from this website:
www.fileformat.info/format/bmp/egff.htm#MICBMP-DMYID.2
for this demo you will need to create a BMP by the name of "heightmap.bmp" and put it in the files section of Basic4GL (or just change the code to your file name and location).
Enjoy....G
Most of you should see the relevance of being able to read BMP files into an array. The obvious example and the one I have included with this reader is for creating height maps based on the luminance of the pixel. This means if you wanted to create a 3D outdoor environment, you could do so in a BMP file in Photoshop and read the data in as opposed to writing a thousand "Data" statements.
This program will work on 24 bit BMPs and 8 bit BMPs in a Windows format with no compression. I got most of the information to create this from this website:
www.fileformat.info/format/bmp/egff.htm#MICBMP-DMYID.2
for this demo you will need to create a BMP by the name of "heightmap.bmp" and put it in the files section of Basic4GL (or just change the code to your file name and location).
Enjoy....G
' BMP File Format Reader, reads data into an array
' by GuppyB, feel free to copy,post,add to demos, and generally use as you please
dim file
dim byteMarker
dim i,j,x,y, dummy
dim fourByte
file = OpenFileRead ("Files/heightmap.bmp") ' substitute your file here make sure to keep in Files folder
if FileError () <> "" then print FileError (): end endif
byteMarker = 0
' ****** Read File Header (this is general file info) 14 bytes ***************
dim filetype1, filetype2
dim filesize
dim reserved1, reserved2
dim BitMapOffset
filetype1 = ReadByte(file): filetype2 = ReadByte(file)
if filetype1<>66 and filetype2<>77 then print "File is not a BMP file" : end endif
' first two bytes of a BMP are the file type and will always be 66 and 77 or chars "B" and "M"
filesize = ReadInt(file) ' read file size
reserved1 = ReadWord(file): reserved2 = ReadWord(file) ' reserved bytes always = 0 , not important
BitMapOffset = ReadInt(file) 'Start position of image in bytes
' ************* Read Bitmap Header (this is image info) 40 bytes **************
dim header2size
dim width, height, planes , absY
dim BitsPerPixel, CompressionType, SizeOfBitMap
dim HorzResolution, VertResolution
dim ColorsUsed, ColorsImportant
dim restOfHeader
header2size = ReadInt(file) 'size in bytes of 2nd header
width = ReadInt(file) : height = ReadInt(file) ' height and width in pixels
planes = ReadWord(file) 'number of planes always = 1
BitsPerPixel = ReadWord(file) 'determines color depth 1,2,4,8,256 colors or 24bit color
CompressionType = ReadInt(file) : SizeOfBitMap = ReadInt(file) 'compression used and SizeOfBitmap will = 0 if uncompressed
HorzResolution = ReadInt(file) : VertResolution = ReadInt(file) 'resolution in pixels per meter
ColorsUsed = ReadInt(file) 'number of colors in palette, if color depth < 24 bit
ColorsImportant = ReadInt(file) 'number of important colors in palette
bytemarker = 54 'we've read 54 bytes in file so far
if header2size > 40 then
restOfHeader = header2size - 40
for i = 1 to restOfHeader
ReadByte(file)
bytemarker = bytemarker + 1
next
endif 'header sizes may vary between BMP vers. so this gets us to end of header
if CompressionType <> 0 then print "Compression not supported" : end endif
' ok so I'm lazy... compression and more info can be found here http://www.fileformat.info/format/bmp/egff.htm#MICBMP-DMYID.2
dim Pixel#(width+1)(height+1)(2) 'set pixel array
if BitsPerPixel = 24 then gosub Load24bit else gosub LoadPalettebits endif
' 24 bit BMPs do not require color palette so we branch here to acccomodate
' ******************************** Sample Use of this loaded Array as a Height Map *******************
dim screenW, screenH
dim HeightMap#(width+1)(height+1)
dim MaxHeight#
dim revY 'reverse Y loop from back to front
dim revX 'reverse X loop
screenW = 1024: screenH = 768 'set to width and height of your screen
MaxHeight# = 50.0
glMatrixMode (GL_PROJECTION)
glLoadIdentity ()
glOrtho (0, screenW, 0, screenH,-1, 1)
glMatrixMode (GL_MODELVIEW)
glDisable (GL_DEPTH_TEST)
glClear (GL_COLOR_BUFFER_BIT)
glPointsize(1)
glDrawBuffer(gl_back)
' assign a height map based on luminance
for y=0 to abs(height )
for x=0 to width
HeightMap#(x)(y)=(0.27*Pixel#(x)(y)(0))+(0.67*Pixel#(x)(y)(1))+(0.06*Pixel#(x)(y)(2))
' equation above approximates luminance
next
next
while true
for y= 0 to abs(height)-1
revY = y ' reverse so that proper polygons are drawn in back
for x= 0 to width-1
revX = width - x
glBegin(GL_QUADS)
glColor3f(Pixel#(revX-1)(revY)(0) , Pixel#(revX-1)(revY)(1) , Pixel#(revX-1)(revY)(2))
glVertex2f((revX-1) + (revY),(screenH - (MaxHeight# +1)) - ((revY) - int(HeightMap#(revX-1)(revY) * MaxHeight#)) )
glColor3f(Pixel#(revX)(revY)(0) , Pixel#(revX)(revY)(1) , Pixel#(revX)(revY)(2))
glVertex2f((revX) + (revY),(screenH - (MaxHeight# +1)) - ((revY) - int(HeightMap#(revX)(revY) * MaxHeight#)) )
glColor3f(Pixel#(revX)(revY+1)(0) , Pixel#(revX)(revY+1)(1) , Pixel#(revX)(revY+1)(2))
glVertex2f((revX) + (revY+1),(screenH - (MaxHeight# +1)) - ((revY+1) - int(HeightMap#(revX)(revY+1) * MaxHeight#)) )
glColor3f(Pixel#(revX-1)(revY+1)(0) , Pixel#(revX-1)(revY+1)(1) , Pixel#(revX-1)(revY+1)(2))
glVertex2f((revX-1) + (revY+1),(screenH - (MaxHeight# +1)) - ((revY+1) - int(HeightMap#(revX-1)(revY+1) * MaxHeight#)) )
glEnd()
next
next
SwapBuffers()
wend
' ************ Load 24 bit data subroutine ****************
Load24bit: 'reading 24 bit data is pretty straight forward
dim blue ,green ,red
if bytemarker <> BitMapOffset then print "Error in Header file": end endif
' check to make sure we are at the start of the bit map data
fourByte = 0 'each scan line must end on a 4 byte line
For y=0 to abs(height)
for x=0 to width-1
if height > 0 then absY = (height) - y else absY = y endif ' if height is positive image loads top up
blue = ReadByte(file)
Pixel#(x)(absY)(2) = blue / 255.0 ' Read Blue, in BMP file structure Blue is 1st so we load array backwards
green = ReadByte(file)
Pixel#(x)(absY)(1) = green / 255.0 ' Read Green, also convert from 0-255 to 0-1.0
red = ReadByte(file)
Pixel#(x)(absY)(0) = red / 255.0 ' Read Red
fourByte = fourByte + 3
if fourByte > 3 then fourByte = fourByte - 4 endif
next
' here is where we calculate how many bytes are left to reach the four byte boundary at the end of the scan line
if fourByte > 0 then for i = 1 to (4 - fourByte): j = ReadByte(file): next : endif
fourByte = 0
next
CloseFile (file)
return
' ************ Load Paletted Data subroutine *****************
LoadPalettebits:
dim Palette(256)(3), pixelColor
' first we establish the three colors for each of the palette numbers
if BitsPerPixel < 8 then print "8 bit BMP only supported":end endif
' more laziness on my part, not too difficult to figure out how to decode 1 and 4 bits
if ColorsUsed = 0 then ColorsUsed = 255 endif 'ColorsUsed = 0 means whole 8 bits used
for i = 0 to ColorsUsed
Palette(i)(0) = ReadByte(file) 'read blue
Palette(i)(1) = ReadByte(file) ' read green
Palette(i)(2) = ReadByte(file) 'read red
ReadByte(file) 'dummy byte at the end of each 3 byte color
bytemarker = bytemarker + 4
next
if bytemarker < BitMapOffset then for i = 1 to BitMapOffset - bytemarker: ReadByte(file):next:endif
' get to the data
fourByte = 0
For y=0 to abs(height)
for x=0 to width-1
if height > 0 then absY = (height) - y else absY = y endif ' if height is positive image loads top up
pixelColor = ReadByte(file)
Pixel#(x)(absY)(2) = Palette(pixelColor)(0) / 255.0 ' Read Blue, in BMP file structure Blue is 1st so we load array backwards
Pixel#(x)(absY)(1) = Palette(pixelColor)(1) / 255.0 ' Read Green, also convert from 0-255 to 0-1.0
Pixel#(x)(absY)(0) = Palette(pixelColor)(2)/ 255.0 ' Read Red
fourByte = fourByte + 1
if fourByte > 3 then fourByte = fourByte - 4 endif
next
' here is where we calculate how many bytes are left to reach the four byte boundary at the end of the scan line
if fourByte > 0 then for i = 1 to (4 - fourByte): j = ReadByte(file): next : endif
fourByte = 0
next
return