24-bit BMP Raster Data tutorial & grayscaling

Source: Internet
Author: User
Tags bmp image
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 possible16 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 Fig. 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), orred! 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 wowould need all red, all green and no blue. being 255 is the maximum for each color, you wowould need an RGB data value of (255,255, 0) to achieve an accurate representation ofyellow.

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 wocould have (100x100) �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's 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;  sImageoriginalImage;  unsigned charsomeChar;  unsigned char*pChar;  longfileSize;  intvectorSize, nColors;  intr, 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;  longvalue=0L;  inti;  unsigned chardummy;  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 255Green 255 Blue 255(0 1) = Red 255Green 255 Blue 255(0 2) = Red 255Green 255 Blue 255(0 3) = Red 255Green 255 Blue 255(0 4) = Red 255Green 255 Blue 255(0 5) = Red 255Green 255 Blue 255(0 6) = Red 255Green 255 Blue 255(0 7) = Red 255Green 255 Blue 255(0 8) = Red 255Green 255 Blue 255(0 9) = Red 255Green 255 Blue 255(0 10) = Red 255Green 255 Blue 255(0 11) = Red 255Green 255 Blue 255(0 12) = Red 0Green 0 Blue 0(0 13) = Red 0Green 0 Blue 0(0 14) = Red 0Green 0 Blue 0(0 15) = Red 0Green 0 Blue 0(0 16) = Red 0Green 0 Blue 0(0 17) = Red 0Green 0 Blue 0(0 18) = Red 0Green 0 Blue 0(0 19) = Red 0Green 0 Blue 0:(8 0) = Red 255Green 255 Blue 0(8 1) = Red 255Green 255 Blue 0(8 2) = Red 255Green 255 Blue 0(8 3) = Red 255Green 255 Blue 0(8 4) = Red 255Green 255 Blue 0(8 5) = Red 255Green 255 Blue 0(8 6) = Red 255Green 255 Blue 0(8 7) = Red 255Green 255 Blue 0(8 8) = Red 255Green 255 Blue 0(8 9) = Red 255Green 255 Blue 0(8 10) = Red 255Green 255 Blue 0(8 11) = Red 255Green 255 Blue 0(8 12) = Red 255Green 255 Blue 255(8 13) = Red 255Green 255 Blue 255(8 14) = Red 255Green 255 Blue 255(8 15) = Red 255Green 255 Blue 255(8 16) = Red 255Green 255 Blue 255(8 17) = Red 255Green 255 Blue 255(8 18) = Red 255Green 255 Blue 255(8 19) = Red 255Green 255 Blue 255:(16 0) = Red 255Green 255 Blue 0(16 1) = Red 255Green 255 Blue 0(16 2) = Red 255Green 255 Blue 0(16 3) = Red 255Green 255 Blue 0(16 4) = Red 255Green 255 Blue 0(16 5) = Red 255Green 255 Blue 0(16 6) = Red 255Green 255 Blue 0(16 7) = Red 255Green 255 Blue 0(16 8) = Red 255Green 255 Blue 0(16 9) = Red 255Green 255 Blue 0(16 10) = Red 255Green 255 Blue 0(16 11) = Red 255Green 255 Blue 0(16 12) = Red 255Green 255 Blue 255(16 13) = Red 255Green 255 Blue 255(16 14) = Red 0Green 255 Blue 0(16 15) = Red 0Green 255 Blue 0(16 16) = Red 0Green 255 Blue 0(16 17) = Red 0Green 255 Blue 0(16 18) = Red 0Green 255 Blue 0(16 19) = Red 0Green 255 Blue 0:

Notice how entry (16, 0) is (Red = 255, Green = 255, Blue = 0) corresponding to a yellow pixel in test24.bmp. and we can see that looking at test24.bmp, it matches precisilely. just remember that in BMP, The raster data is stored from left to right and
Bottom to top-so Row 16, column 0 is somewhere in the top left corner!

Explanation

To get preliminary code explanation, please see my
Raster Data tutorial. the difference between this code and my 8-bit raster code is that instead of 1 byte representing a pixel (8-bit ), we now have 3 bytes representing each pixel (24-bit ). so we cannot read the value of the pixel intensity and then move
On to the next row-column entry. We have to read 3 different bytes! The algorithm below was used to do this:

      /*----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);    
Converting a 24-bit BMP to gray scale

We want to take the test24.bmp and grayscale it, or convert it from a 24-bit to an 8-bit BMP. we'll call our new grayscaled BMP "gray24.bmp ". A formula for converting a RGB pixel value to a grayscale value is shown below:

grayValue = 0.299*redValue + 0.587*greenValue + 0.114*blueValue

First, I copied the header and info header from the input BMP to the output BMP. This process is described in myraster data tutorial. They are the same with
Exception of the file size, bits/pixel value, and the number of colors. We manipulate them by using the following code

  /*----CHANGE BIT DEPTH FROM 24 TO 8----*/  fseek(bmpOutput, 28, SEEK_SET);  *pLong = (unsigned long)(8);  fwrite(pLong, sizeof(unsigned long), 1, bmpOutput);

The color tables, however, are not identical. there is no color table in a 24-bit BMP (see above), while there is one in a grayscale image. therefore, instead of copying the color table like we have been, we are actually going to have to create one. I did
This by just copying the color table of another grayscale BMP.

createColorTable(grayBmpInput, bmpOutput);

The following portion of code converts a 24-bit BMP file to grayscale. The differences from raster24.c are in red.

To be compiled with Turbo C
Note: Download
Gray24.zip rather than cutting and pasting from below.

      /*-----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;      /*-----USE FORMULA TO CONVERT RGB VALUE TO GRAYSCALE-----*/      grayValue = (int)(0.299*redValue + 0.587*greenValue + 0.114*blueValue);      /*-----PRINT TO TEXT FILE-----*/      fprintf(rasterOutput, "(%d %d) = \tRed \t%d", r, c, redValue);      fprintf(rasterOutput, "\tGreen \t%d \tBlue \t%d \tGray \t%d\n", greenValue, blueValue, grayValue);      /*-----WRITE TO NEW BMP FILE------*/      *pChar = grayValue;      fseek(bmpOutput, (54 + 4*256), SEEK_SET);      fwrite(pChar, sizeof(char), 1, bmpOutput);
 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.