Date: 02-16-2022
Return to Index
created by gbSnippets
'Because the structure of bitmap file is well-defined, a programmer
'can read the file without using API. Simple Get/Put statement are
'all that is required.
'The image color data can be read directly into a two-dimensional
'array, corresonding to the (x,y) positions of the image pixels.
'While in array form, the pixel color data can be modified by the
'application using customized code (there are no API to modify the
'color data within the array).
'Once changes are made to the image color data (the array), the
'two bitmap data structures and the image color data array can be
'written back to a file, again without the use of API.
'Specifically, a bitmap file (*.bmp) consists of the following structure:
1. BITMAPFILEHEADER 'data structure
2. BITMAPINFOHEADER 'data structure
4. ColorBytes '3 bytes per pixel (with padding for Word alignment)
'Primary Code:
'This code revolves around using GET/PUT to read/write the two header
'structures (BITMAPFILEHEADER and BITMAPINFOHEADER), was well as to read/write
'the image color data into a Byte array.
'Create Buffer array to hold image color data + padding bytes
Dim Buffer(w*3+padding-1,h-1) As Byte 'pixel color array data (0-based array)
'Open input file
Open fSource For Binary as #1
Get #1, , bmpheader 'get BITMAPFILEHEADER
Get #1, , bmpinfo 'get BITMAPINFOHEADER
Get #1, bmpheader.bfOffBits+1, Buffer() 'read image color data into Byte array
Close #1
'Open output file
Open fTarget For Binary as #1
Put #1,, bmpheader 'BITMAPFILEHEADER
Put #1,, bmpinfo 'BITMAPINFOHEADER
Put #1,, Buffer() 'write image color data (includes padding bytes)
Close #1
'Compilable Example: (Jose Includes)
'GET is used to read the file header, info header, and image color data.
'PUT is used to return the headers/color data to a file. In this example
'the color data is edited and the changes written to a new bitmap file,
'all without displaying the image.
#Compiler PBWin 9, PBWin 10
#Compile EXE
#Dim All
%Unicode=1
#Include "Win32API.inc"
#Resource "gbsnippets.pbr"
Global hDlg, hGraphic, hBMP, DC_graphic, DC_BMP as DWord
Function PBMain() As Long
Dialog New Pixels, 0, "Test Code",300,300,200,200, %WS_OverlappedWindow To hDlg
Control Add Button, hDlg, 100,"Read From File", 20,10,150,20
Dialog Show Modal hDlg Call DlgProc
End Function
CallBack Function DlgProc() As Long
If CB.Msg = %WM_Command AND CB.Ctl = 100 AND CB.Ctlmsg = %BN_Clicked Then
Local w,h As Long
ReadEditSaveBitmapFile("cowgirl.bmp", "test.bmp", w, h)
'display the results in a Graphic Control
Control Add Graphic, hDlg, 900, "", 50,50,w,h
Graphic Attach hDlg, 900 : Graphic Render "test.bmp", (0,0)-(w-1,h-1) :
End If
End Function
Sub ReadEditSaveBitmapFile (fSource As String, fTarget As String, w As Long, h as Long) 'w,h are returned values
Local bmpheader As BITMAPFILEHEADER, bmpinfo As BITMAPINFOHEADER, padding, x, y As Long
'Open the file
Open fSource For Binary as #1
Get #1, , bmpheader 'get BITMAPFILEHEADER
Get #1, , bmpinfo 'get BITMAPINFOHEADER
'Optionally verify the file is of interest - Bitmap, 24bit, non-compressed
If bmpheader.bfType <> CVI("BM") Then MsgBox ("bad file - ") + Mks$(bmpheader.bfType) : Exit Sub 'want bitmap file
If bmpInfo.biCompression <> %BI_RGB Then MsgBox ("bad file - compressed") : Exit Sub 'want uncompressed
If bmpInfo.biBitcount <> 24 Then MsgBox ("bad file - " + Str$(bmpInfo.biBitCount)) : Exit Sub 'want 24bit only
'A two-dimension Byte array is used to hold the image color data + padding bytes
w = bmpinfo.biWidth
h = bmpinfo.biHeight
padding = (4 - (w*3) Mod 4) Mod 4
Dim Buffer(w*3+padding-1,h-1) As Byte 'pixel color array data (0-based array)
'read the buffer, which contains padded, upside-down, and BGR image color data
Get #1, bmpheader.bfOffBits+1, Buffer()
Close #1
'Optional example of modifying the image color data within the Buffer() array
For y = 0 to h-1 'each row
For x = 0 To w*3-1 '1 byte at a time, 1 pixel = 3 bytes, BGR byte order, ignores padding bytes
If y <= (h-1)/2 Then Buffer(x,y) = 128 'top half darker RGB = 64,64,64 vs 128,128,128
Next x
Next y
'Open output file
Open fTarget For Binary as #1
Put #1,, bmpheader 'BITMAPFILEHEADER
Put #1,, bmpinfo 'BITMAPINFOHEADER
Put #1,, Buffer() 'image data (size is paddesize)
Close #1
End Sub
'gbs_00514
'Date: 03-10-2012
http://www.garybeene.com/sw/gbsnippets.htm