INTERNAL: Reading Monochrome Bitmap Files
Topic:
The purpose of this Tech Tip is to provide information and sample code that can be used to read monochrome bitmap files with IDL. The monochrome bitmap format is not supported by the routine READ_BMP.
Discussion:
Monochrome bitmap files are images where each bit of data in the file corresponds to a pixel in the image. It is more common to see images in which a byte of data corresponds to a pixel in the image. Therefore, each pixel in the image can have a value ranging from 0 to 255. With monochrome bitmap images each pixel can have a value of 1 (white) or 0 (black). Monochrome bitmap images can be generated using MS Paint. A example image is shown below:
Reading monochrome bitmap images with IDL can be difficult because there is not BIT type. Therefore, the data has to be read in as bytes, which then need to be expanded into their bit values. In order to read the file, you must know something about the bitmap file format. The
Wikipedia page for bitmap files has some good information about this topic. The table below shows the bitmap file format information that can be used to read a monochrome bitmap file.
Byte Number |
Field |
Type |
Use or Explanation |
1-2 |
File type |
2 byte array |
Confirms file BMP type ("BM") |
3-6 |
File size (BYTES) |
Long |
Used to determine array size needed to read image |
7-10 |
Junk |
Long |
Not used |
11-14 |
Byte offset of BMP data |
Long |
Byte number where image data starts |
15-18 |
Header bytes |
Long |
Byte length of header data |
19-22 |
Width of image (Pixels) |
Long |
Used to determine array size needed to read image |
23-26 |
Height of image (Pixels) |
Long |
Used to determine array size needed to read image |
27-28 |
Bit planes |
Integer |
Not very useful for monochrome images |
27-28 |
Bits per pixel |
Integer |
Confirms monochrome image (should equal 1) |
One thing that complicates the reading of monochrome bitmap files is that the files are padded so that the stored data is a multiple of 4 bytes. To account for this problem, you can check if the modulous of the image width (bytes) and 32 (4 bytes; word size) is equal to zero. If it is equal to zero, then the image width is equal to width of the data stored in the file. If it is not equal to zero, then the image width will not be equal to the data stored in the file because extra zeros were added to the data to make it a multiple of 32. To account for this, you can use the equation below to determine the width of the data inside the file:
data width = (image_width_pix/32L+1)*32L
Below is an example function called "read_mono_bmp" that reads monochrome bitmap images and outputs an 2-D array or binary data. This function uses the BINARY command from the
Coyote library.
NOTE: "read_mono_bmp" is met to be an example program. It has not been robustly tested and it might be very slow or not work with some files. This code is not official Exelis VIS code.
An example of how to use the "read_mono_bmp" routine is shown below:
IDL>img = read_mono_bmp(DIALOG_PICKFILE()) ; pick a monochrome bmp image
IDL> tvscl, img
'img' is a 2-D array of ones and zeros. Therefore, to display the image (without further processing) the user must use TVSCL instead of TV.
Solution:
;+
;
; This is a program that reads in a Monochrome Bitmap file
; and ouputs image data in ones and zeros
;
;
; :Uses: Read_binary, binary (Coyote Library)
; :Author: David Staruck, Exelis VIS, 2011
;-
function read_mono_bmp, file_a
on_error, 2
openu, lun, file_a, /GET_LUN
f_type=BYTARR(2); type of file should be BM
f_size=0L ; size of file in bytes
junk=0L ; empty space
f_off=0L ; Image data offset from top of file
head_bytes=0L ;bytes in header
width_pix=0L ;width of image (pixels)
height_pix=0L ;height of image (pixels
biplanes=0 ; number of bit planes
bibitcount=0 ; bit per pixel count (should be 1)
img_index=0L ;index used for final image
;read some of the header infomation about the file (don't care about color info)
readu, lun, f_type, f_size, junk, f_off
readu, lun, head_bytes, width_pix, height_pix, biplanes, bibitcount
;Error handle
;Confirm file is a bitmap image
if string(f_type) ne 'BM' then message, 'File is not in bitmap format'
;Cofirm file is a monochrome bitmap image
if bibitcount ne 1 then message, 'File is not a monochrome bitmap image'
close, lun ;close the file. will reopen with read_binary function
data_width_pix = width_pix ;width of image in file (with padding)
;Calculate data width pixel numbers. Add extra data to account for padding.
if (data_width_pix MOD 32 NE 0) then begin
mult = data_width_pix/32L + 1
data_width_pix = mult*32L
endif
;Pixel array rowsize =(pixel_width*BBP)/32 * 4
x=byte(width_pix/32.*4) ;BBP (bits per pixel) equals 1 in this case
;set up array dimensions
dim=[x, height_pix]
;use read binary to get image information (in BYTES)
img=READ_BINARY(file_a, DATA_DIMS=dim, DATA_START=f_off)
;declare final image array
tmp_img=BYTARR(data_width_pix,height_pix)
;loop through each element in img and convert BYTE to Binary and fill fin_img with information
for i = 0L, N_ELEMENTS(img)-1 do begin
b=binary(img[i]) ;used binary function from Coyote library
for j = 0L, N_ELEMENTS(b)-1 do begin
tmp_img[img_index]=b[j]
img_index=img_index+1
endfor
endfor
;Display the final image
;tvscale, fin_img
fin_img=tmp_img[0:width_pix-1, *]
return, fin_img