Dark Bit Factory & Gravity
PROGRAMMING => Freebasic => Topic started by: rdc on December 25, 2008
-
This short program will convert a 24/32 bit bitmap into a color data array that can then be used to draw on the screen. I use this quite a bit in my programs since accessing an array is much faster than accessing image data. Do not compile this with -s gui since it uses the console to gather input. You would use the output array in this fashion: (uinteger) pixel = arrayname(x + y * bmpwidth). Real world example: prch = parch(x + y * parchw), where prch is a uniteger, x and y are the pixel coordinates, and parchw is the bitmap width.
It might be useful for someone.
'Convert.bas
'Richard Clark
'Extracts the color information from a 24/32 bit bitmap
'to an include file for use in an FB program.
'Using a graphic screen and the Point function.
'Do not compile with -s gui, as this uses the console screen
'for input.
'Public doman, use any way you like.
dim as integer iw, ih, sw, sh, dp = 32
dim as string iname, aname, oname
dim as integer x, y, i, fh, cnt
Input "Enter bitmap width";iw
if iw = 0 then iw = 256
Input "Enter bitmap height";ih
if ih = 0 then ih = 256
Input "Enter bitmap filename (including extension)";iname
Input "Enter data array name";aname
Input "Enter export file name (including extension ex: pic.bi)";oname
Input "Enter graphic screen width";sw
if sw = 0 then sw = 640
Input "Enter graphic screen height";sh
if sh = 0 then sh = 480
if iw <= 0 or ih <= 0 then
print "Width and height must be greater than zero."
sleep
end
end if
if len(iname) = 0 or len(aname) = 0 or len(oname) = 0 then
print "No values given for filename, array name or output file name."
sleep
end
end if
if sw <= 0 or sh <= 0 or dp <= 0 then
print "Screen dimensions and depth must be greater than zero."
sleep
end
end if
if len(dir(iname)) = 0 then
print "Cannot find " & iname &"."
sleep
end
end if
fh = freefile
if open(oname for output as #fh) <> 0 then
print "Cannot open output file."
sleep
end
end if
dim bmvals(iw * ih) as uinteger
screenres sw, sh, dp
if Screenptr = 0 then
print "Cannot set graphic screen."
sleep
close fh
end
end if
bload iname
'Print out header information
Print #fh, "'Useage: (uinteger) pixel = ";aname; "(x + y * ";aname & "w)"
print #fh, "Const ";Trim(aname);"w = ";Str(iw)
print #fh, "Const ";trim(aname);"h = ";Str(ih)
print #fh, "Dim Shared " & trim(aname) & "(" & str(iw * ih) & ") As UInteger = { _"
for x = 0 to iw - 1
for y = 0 to ih - 1
bmvals(x + y * iw) = point(x, y)
next
next
for i = lbound(bmvals) to ubound(bmvals)
cnt += 1
if i = ubound(bmvals) then
print #fh, "&h" & hex(bmvals(i)) & "}"
else
if cnt < 8 then
print #fh, "&h" & hex(bmvals(i)) & ",";
else
print #fh, "&h" & hex(bmvals(i)) & ", _"
cnt = 0
end if
end if
next
close fh
end
-
Cheers for sharing it dude, nice one :)
-
Cheers Rick :) Have some good karma for this useful tool :D
-
Not only is it very usefull, you have also taught me about saving data.
Cheers Squire,
Clyde.
-
No problem guys. counting_pine posted a trick for getting the dimensions of a bitmap:
'' open BMP file
filenum = FreeFile()
If Open( iname For Binary Access Read As #filenum ) <> 0 Then
Print "Cannot find " & iname & "."
Sleep
End
EndIf
' retrieve BMP dimensions
Get #filenum, 19, iw
Get #filenum, 23, ih
Close #filenum
dim bmvals(iw * ih) as uinteger
The iw is the width, and the ih is the height. Make things a bit easier. Here is a loader he made and posted on the FB forums:
'' A function that creates an image buffer with the same
'' dimensions as a BMP image, and loads a file into it.
'' Code by counting_pine
Function bmp_load( ByRef filename As String ) As Any Ptr
Dim As Integer filenum, bmpwidth, bmpheight
Dim img As Any Ptr
'' open BMP file
filenum = FreeFile()
If Open( filename For Binary Access Read As #filenum ) <> 0 Then Return 0
'' retrieve BMP dimensions
Get #filenum, 19, bmpwidth
Get #filenum, 23, bmpheight
Close #filenum
'' create image with BMP dimensions
img = ImageCreate( bmpwidth, Abs(bmpheight) )
If img = 0 Then Return 0
'' load BMP file into image buffer
If BLoad( filename, img ) <> 0 Then ImageDestroy( img ): Return 0
Return img
End Function
This returns an FB image. I am using it like this:
'Load the font into the buffer.
fontbuffer = bmp_load("media/bradley.bmp")
If fontbuffer = 0 Then
Print "Could not load font file: bradley.bmp."
Sleep
Exit Sub
EndIf
Makes it real easy to load up your graphic data in FB. counting-pine gets the props here.
-
I am not sure it useful to you, but I did some code long time ago to get the width and height of .png and .jpg images without loading the complete file. It is written in bmax, but should be fairly straight forward to convert to other basic type languages. I have not used freebasic for years, so unfortunaltely I have forgotten most of the syntax, otherwise I might have given it a try myself.
But if this sounds useful to you, then here is the code:
Local width:Int = 0
Local height:Int = 0
imageWidthHeightPNG("4.png",width,height)
Print Hex(width)+","+width
Print Hex(height)+","+height
imageWidthHeightJPG("4.jpg",width,height)
Print Hex(width)+","+width
Print Hex(height)+","+height
End
Function imageWidthHeightPNG(imagePath:String,width:Int Var, height:Int Var)
Local file:TStream = OpenStream(imagePath)
If ReadShort(file) <> $5089 Then Return False ' not a png image file
SeekStream(file,18)
width = ReadByte(file)*256
width :+ ReadByte(file)
SeekStream(file,22)
height = ReadByte(file)*256
height :+ ReadByte(file)
CloseStream(file)
End Function
Function imageWidthHeightJPG(imagePath:String,width:Int Var, height:Int Var)
Local file:TStream = OpenStream(imagePath)
If ReadShort(file) <> $D8FF Then Return False ' not a jpg image file
Local b1:Byte,b2:Byte,test:Byte=$E1
Local jump:Int
While Not Eof(file)
' locate jump instructions
Repeat
b1 = ReadByte(file)
Until b1 = $FF
b2 = ReadByte(file)
If b2 > $E0 And b2 < $EE Then ' jump instruction found
jump = ReadByte(file)*256+ReadByte(file)
SeekStream(file,StreamPos(file)+jump-2)
End If
If b2 = $EE Then ' no more jumps
' find width & height info
Repeat
b1 = ReadByte(file)
If b1 = $FF Then b2 = ReadByte(file)
Until (b1 = $FF And b2 = $C0) Or (b1 = $FF And b2 = $C1) Or (b1 = $FF And b2 = $C2) Or (b1 = $FF And b2 = $C3)
' skip 3 bytes
SeekStream(file,StreamPos(file)+3)
height = ReadByte(file)*256
height :+ ReadByte(file)
width = ReadByte(file)*256
width :+ ReadByte(file)
CloseFile(file)
Return
End If
Wend
End Function
-
Splendid stuff both of yas! Thanks :)
I think I know why Im having bitmap troubles; just noticed the abs on the heght. Either that or my bitmaps are being corrupted by the conversion process some how.
-
The abs() is there because Windows BMP files are most often stored upside down. When it does this, it negates the height.
You might find that even with the abs, your images appear upside down.
Jim
-
You might as well use .png instead of .bmp since its a packaged format, but without quality loss, so you will still get the image as it was ment, but you save a lot on the file size.
-
I think that's true in nearly every case when you want a 24bit graphic, but when BMP is the win is when you use it to do a 4bit or 8bit bitmap, especially with RLE encoding. In that case you get a 16 or 256 colour graphic which is truly tiny, and PNG cannot match it.
Jim
-
Great snippets of wisdom, I must say so myself.
Zawran: With your png source, do you need ZLib ?
-
do you need ZLib
It should work just as it is.