'' '' '' Chapter 9 - File I/O example: Loading and analyzing the header of a BMP file '' '' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 'The BMP Header format '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Type BMP_Header Field = 1 'The fields listed earlier magicNum As uShort fileSize As uInteger res1 As uShort res2 As uShort pixelOffset As uInteger bmiSize As uInteger imgWidth As uInteger imgHeight As uInteger planes As uShort bpp As uShort 'Other fields that don't matter biCompression As uInteger biSizeImage As uInteger horizontal_res As uInteger vertical_res As uInteger biClrUsed As uInteger biClrImportant As uInteger End Type '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 'Load the header of a BMP, check its validity, and print out diagnostic messages '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Function checkBMP (fileName As String) As Integer 'File handle we'll use to load the BMP Dim As Integer bmpfhndl 'File handle for the log file we'll write messages to Dim As Integer outfhndl 'We'll use this to keep track of what byte offset we're at in the BMP 'Remember, binary file offsets in FreeBASIC start with 1, not 0 like everyone else. Dim As Integer fpos = 1 'Where we'll load our BMP header to Dim As BMP_Header bmphdr 'Open the log file first outfhndl = FreeFile() Open "checkbmp.log" For Output As #outfhndl 'Open the BMP bmpfhndl = FreeFile() Open fileName For Binary As #bmpfhndl 'If an error occurs or the file is empty, return 0 If Err Or Eof(bmpfhndl) Then 'Print the error message, close the files, return 0 for failure Print "Error loading BMP - file inaccessible or empty." Print #outfhndl, "Error loading BMP - file inaccessible or empty." Close #outfhndl Close #bmpfhndl Return 0 End If 'This is how you load a binary file field-by-field. 'Keep track of the file position and as you go through each field, increment 'the counter by the size of the field. Get #bmpfhndl, fpos, bmphdr.magicNum fpos += SizeOf(bmphdr.magicNum) Get #bmpfhndl, fpos, bmphdr.fileSize fpos += SizeOf(bmphdr.fileSize) 'Now we've loaded the magic number and the file size. Before we do anything else, 'let's make sure they match properly. If bmphdr.magicNum <> &h4D42 Then 'Print the error message, close the files, return 0 for failure Print "Error loading BMP - file signature does not match ""BM""." Print #outfhndl, "Error loading BMP - file signature does not match ""BM""." Close #outfhndl Close #bmpfhndl Return 0 End If If bmphdr.fileSize <> Lof(bmpfhndl) Then 'Print the error message, close the files, return 0 for failure Print "Error loading BMP - header-registered file size does not match actual file size." Print #outfhndl, "Error loading BMP - header-registered file size does not match actual file size." Close #outfhndl Close #bmpfhndl Return 0 End If 'At this point, we're pretty sure it's a valid BMP, so we'll continue loading the other fields. 'Just skip the fields we don't care about fpos += SizeOf(bmphdr.res1) fpos += SizeOf(bmphdr.res2) Get #bmpfhndl, fpos, bmphdr.pixelOffset fpos += SizeOf(bmphdr.pixelOffset) Get #bmpfhndl, fpos, bmphdr.bmiSize fpos += SizeOf(bmphdr.bmiSize) Get #bmpfhndl, fpos, bmphdr.imgWidth fpos += SizeOf(bmphdr.imgWidth) Get #bmpfhndl, fpos, bmphdr.imgHeight fpos += SizeOf(bmphdr.imgHeight) Get #bmpfhndl, fpos, bmphdr.planes fpos += SizeOf(bmphdr.planes) Get #bmpfhndl, fpos, bmphdr.bpp fpos += SizeOf(bmphdr.bpp) 'Print information on the screen Print "Pixel Offset: &h" + Hex(bmphdr.pixelOffset) Print "BMI Size: &h" + Hex(bmphdr.bmisize) Print "" Print "Image Width: " + Str(bmphdr.imgWidth) Print "Image Height: " + Str(bmphdr.imgHeight) Print "Planes: " + Str(bmphdr.planes) Print "BPP: " + Str(bmphdr.bpp) Print "Actual bytes per pixel: " + Str((bmphdr.planes)*(bmphdr.bpp)/8) 'Now print it all over again into our log file Print #outfhndl, "Pixel Offset: &h" + Hex(bmphdr.pixelOffset) Print #outfhndl, "BMI Size: &h" + Hex(bmphdr.bmisize) Print #outfhndl, "" Print #outfhndl, "Image Width: " + Str(bmphdr.imgWidth) Print #outfhndl, "Image Height: " + Str(bmphdr.imgHeight) Print #outfhndl, "Planes: " + Str(bmphdr.planes) Print #outfhndl, "BPP: " + Str(bmphdr.bpp) Print #outfhndl, "Actual bytes per pixel: " + Str((bmphdr.planes)*(bmphdr.bpp)/8) 'Close the log file and the BMP itself Close #outfhndl Close #bmpfhndl 'Return -1 for success Return -1 End Function '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 'The main program '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 'Most of the work is done in the function checkBMP(), thus this part is very short Print "Checking BMP..." Print "" checkBMP("test.bmp") Print "" Print "Done." Sleep ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''