24-Bit BMP Raster Data Tutorial & Grayscaling
Raster Data Tutorial (24-Bit)
Author: Bill Green (2002)
HOME EMAIL
This tutorial assumes the reader knows:
(1) Data is stored left to right and bottom to top in a BMP.
(2) How to develop source code to read BMP header and info header (i.e. width, height & # of colors).
(3) How to develop source code to read raster data
INTRODUCTION
There are a possible 256 colors (2^8) that can be stored in a 8-bit image with 255 being the maximum. Likewise, a 24-bit true color BMP has a possible 16 million colors (2^24). In a 24-bit BMP image, a pixel represents a RGB (Red Green Blue) data value. The pixel's RGB data value shows how much Red, Green and Blue are in that particular pixel. One pixel has 3 8-bit colors in it each having an intensity value between 0-255. So a pixel with a data value of (255, 0, 0) is equivalent to (Red=255, Green=0, and Blue=0), or Red! And the composite of the RGB color values produces that pixels actual color. As another example, we know that red and green make yellow. Therefore we would need all red, all green and no blue. Being 255 is the maximum for each color, you would need an RGB data value of (255, 255, 0) to achieve an accurate representation of yellow.
A 24-Bit BMP file structure is slightly different than an 8-Bit BMP file structure. There is no color table for any BMP with a bits/pixel value > 8. The table below shows how the pixel data is stored from the first byte to the last in a 24-Bit BMP.
TABLE 1: 24-Bit BMP File Structure
Byte # to fseek file pointer Information
0
Signature
2
File size
18
Width (number of columns)
22
Height (number of rows)
28
Bits/pixel
46
Number of colors used
54
Start of raster data in a 24-Bit BMP
The raster data starts at byte 54. The size of the raster data is (width x height) � 1 bytes. Therefore, a 100 row by 100 column 24-bit image would have (100 x 100) � 1 = 9,999 bytes of raster data starting at byte 54 and continuing to the end of the BMP.
READING 24-Bit BMP RASTER DATA
TEST24.bmp is a 20 row by 20 column BMP image which we will use to read raster data from. The top left portion of TEST24.bmp is yellow and has an RGB pixel value of (255, 255, 0). The bottom right portion is black with an RGB value of (0, 0, 0). The top right portion is green with an RGB value of (0, 255, 0), and the remainder of TEST24.bmp is white (255, 255, 255).
(TEST24.bmp is scaled up here to a 100 by 100 BMP,
so be sure and download the zip file to test out your raster data program.)
TEST24.bmp contains 20 rows and 20 columns, so we know we will have 400 bytes of raster data. We also know the raster data will start at byte #54. Knowing this, let抯 try our first program to read raster data and print it to a text file.
To be compiled with Turbo C
Note: download raster24.zip rather than cutting and pasting from below.
#include (stdio.h)
#include (stdlib.h)
#include (math.h)
long getImageInfo(FILE*, long, int);
typedef struct {int rows; int cols; unsigned char* data;} sImage;
int main(int argc, char* argv[])
{
FILE *bmpInput, *rasterOutput;
sImage originalImage;
unsigned char someChar;
unsigned char *pChar;
long fileSize;
int vectorSize, nColors;
int r, c;
/*--------INITIALIZE POINTER----------*/
someChar = '0';
pChar = &someChar;
if(argc < 2)
{
printf("Usage: %s bmpInput.bmp\n", argv[0]);
exit(0);
}
printf("Reading file %s\n", argv[1]);
/*----DECLARE INPUT AND OUTPUT FILES----*/
bmpInput = fopen(argv[1], "rb");
rasterOutput = fopen("data24.html", "w");
fseek(bmpInput, 0L, SEEK_END);
/*-----GET BMP INFO-----*/
originalImage.cols = (int)getImageInfo(bmpInput, 18, 4);
originalImage.rows = (int)getImageInfo(bmpInput, 22, 4);
fileSize = getImageInfo(bmpInput, 2, 4);
nColors = getImageInfo(bmpInput, 46, 4);
/*----PRINT BMP INFO TO SCREEN-----*/
printf("Width: %d\n", originalImage.cols);
printf("Height: %d\n", originalImage.rows);
printf("File size: %ld\n", fileSize);
printf("Bits/pixel: %d\n", getImageInfo(bmpInput, 28, 4));
printf("No. colors: %d\n", nColors);
/*----FOR 24-BIT BMP, THERE IS NO COLOR TABLE-----*/
fseek(bmpInput, 54, SEEK_SET);
/*-----------READ RASTER DATA-----------*/
for(r=0; r<=originalImage.rows-1; r++)
{
for(c=0; c<=originalImage.cols-1; c++)
{
/*----READ FIRST BYTE TO GET BLUE VALUE-----*/
fread(pChar, sizeof(char), 1, bmpInput);
blueValue = *pChar;
/*-----READ NEXT BYTE TO GET GREEN VALUE-----*/
fread(pChar, sizeof(char), 1, bmpInput);
greenValue = *pChar;
/*-----READ NEXT BYTE TO GET RED VALUE-----*/
fread(pChar, sizeof(char), 1, bmpInput);
redValue = *pChar;
/*---------PRINT TO TEXT FILE---------*/
fprintf(rasterOutput, "(%d %d) = \tRed \t%d", r, c, redValue);
fprintf(rasterOutput, "\tGreen \t%d \tBlue \t%d\n", greenValue, blueValue);
}
}
fclose(bmpInput);
fclose(rasterOutput);
return 0;
}
/*--------SUBPROGRAMS------------*/
long getImageInfo(FILE* inputFile, long offset, int numberOfChars)
{
unsigned char *ptrC;
long value=0L;
int i;
unsigned char dummy;
dummy = '0';
ptrC = &dummy;
fseek(inputFile, offset, SEEK_SET);
for(i=1; i<=numberOfChars; i++)
{
fread(ptrC, sizeof(char), 1, inputFile);
/* calculate value based on adding bytes */
value = (long)(value + (*ptrC)*(pow(256, (i-1))));
}
return(value);
}
Running your raster data program, you will get an ASCII file called data24.txt with some entries looking like the following:
(0 0) = Red 255 Green 255 Blue 255
(0 1) = Red 255 Green 255 Blue 255
(0 2) = Red 255 Green 255 Blue 255
(0 3) = Red 255 Green 255 Blue 255
(0 4) = Red 255 Green 255 Blue 255
(0 5) = Red 255 Green 255 Blue 255
(0 6) = Red 255 Green 255 Blue 255
(0 7) = Red 255 Green 255 Blue 255
(0 8) =
补充:软件开发 , C++ ,