Introduction to Audio and Video - 03-RGB to BMP Pictures

Posted by rockstarmike on Fri, 13 Sep 2019 11:00:38 +0200

Directory of Audio and Video Introduction Articles

BMP file format parsing

BMP file is composed of four parts: file header, bitmap information header, color information and graphics data.

Bitmap file header (14 bytes) Bitmap header (40 bytes) Color information graphic data

  • The total number of file headers and information headers is 54 bytes.
  • RGB data section:

RGB24 files are stored in the order of RGB, RGB, RGB... RGB
BMP file RGB data storage order is BGR, BGR, BGR... BGR

bitmap-file header

Bitmap file header is divided into four parts, a total of 14 bytes

Name Occupancy space content Example data
bfType 2 byte The logo is "BM" BM
bfSize 4 byte Size of the whole BMP file 0x000C0036(786486)
bfReserved1 2 byte Reserved word 0
bfReserved2 2 byte Reserved word 0
bfOffBits 4 byte Offset number, that is, the size of bitmap file header + bitmap information header + palette 0x36(54)

Bitmap header

Bitmap headers total 40 bytes

Name Occupancy space content Example data
biSize 4 byte The size of the bitmap header is 40 0x28(40)
biWidth 4 byte Bitmap width, in pixels 0x200(512)
biHeight 4 byte The height of a bitmap in pixels 0x200(512)
biPlanes 2 byte Fixed value 1 1
biBitCount 2 byte Bits per pixel 1-black-and-white, 4-16, 8-256, 24-true, 32-with alpha channels 0x18(24)
biCompression 4 byte Compression mode, BI_RGB(0) is uncompressed 0
biSizeImage 4 byte The number of bytes occupied by all the bitmap pixels, BI_RGB can be set to 0. 0x0C
biXPelsPerMeter 4 byte Horizontal Resolution (Pixel/m) 0
biYPelsPerMeter 4 byte Vertical Resolution (Pixel/m) 0
biClrUsed 4 byte If the number of colors used by the bitmap is 0, then the biBitCount power of the number of colors is 2 0
biClrImportant 4 byte Important number of colours, 0 represents all colours are important 0

Converting RGB24 Pixel Point Data into BMP Format Pictures

Conversion code:

#include <stdio.h>
#include <stdlib.h>

// Seven Colors of Rainbow
u_int32_t rainbowColors[] = {
        0XFF0000, // red
        0XFFA500, // orange
        0XFFFF00, // yellow
        0X00FF00, // green
        0X007FFF, // young
        0X0000FF, // blue
        0X8B00FF  // purple
};

/*bmp file header*/
typedef struct {
    unsigned int   bfSize;           /* Size of file */
    unsigned short bfReserved1;      /* Reserved */
    unsigned short bfReserved2;      /* ... */
    unsigned int   bfOffBits;        /* Offset to bitmap data */
} BitmapFileHeader;

/*bmp info header*/
typedef struct {
    unsigned int   biSize; /* Size of info header */
    int            biWidth; /* Width of image */
    int            biHeight; /* Height of image */
    unsigned short biPlanes; /* Number of color planes */
    unsigned short biBitCount; /* Number of bits per pixel */
    unsigned int   biCompression; /* Type of compression to use */
    unsigned int   biSizeImage; /* Size of image data */
    int            biXPelsPerMeter; /* X pixels per meter */
    int            biYPelsPerMeter; /* Y pixels per meter */
    unsigned int   biClrUsed; /* Number of colors used */
    unsigned int   biClrImportant; /* Number of important colors */
} BitmapInfoHeader;

void writeRGBToBmp(char *filename, int width, int height) {
    FILE *bitmapFile = fopen(filename, "wb");
    if(!bitmapFile) {
        printf("Could not write file \n");
        return;
    }

    uint16_t bfType = 0x4d42;

    BitmapFileHeader fileHeader;
    fileHeader.bfReserved1 = 0;
    fileHeader.bfReserved2 = 0;
    fileHeader.bfSize = 2 + sizeof(BitmapFileHeader) + sizeof(BitmapInfoHeader) + width*height*3;
    fileHeader.bfOffBits = 0x36;

    BitmapInfoHeader infoHeader;
    infoHeader.biSize = sizeof(BitmapInfoHeader);
    infoHeader.biWidth = width;
    infoHeader.biHeight = height;
    infoHeader.biPlanes = 1;
    infoHeader.biBitCount = 24;
    infoHeader.biSizeImage = 0;
    infoHeader.biCompression = 0;
    infoHeader.biXPelsPerMeter = 5000;
    infoHeader.biYPelsPerMeter = 5000;
    infoHeader.biClrUsed = 0;
    infoHeader.biClrImportant = 0;

    fwrite(&bfType, sizeof(bfType), 1, bitmapFile);
    fwrite(&fileHeader, sizeof(fileHeader), 1, bitmapFile);
    fwrite(&infoHeader, sizeof(infoHeader), 1, bitmapFile);

    // Write image data
    for (int i = 0; i < width; ++i) {

        // Current color
        u_int32_t currentColor = rainbowColors[0];
        if(i < 100) {
            currentColor = rainbowColors[0];
        } else if(i < 200) {
            currentColor = rainbowColors[1];
        } else if(i < 300) {
            currentColor = rainbowColors[2];
        } else if(i < 400) {
            currentColor = rainbowColors[3];
        } else if(i < 500) {
            currentColor = rainbowColors[4];
        } else if(i < 600) {
            currentColor = rainbowColors[5];
        } else if(i < 700) {
            currentColor = rainbowColors[6];
        }
        // Current color R component
        u_int8_t R = (currentColor & 0xFF0000) >> 16;
        // Current color G component
        u_int8_t G = (currentColor & 0x00FF00) >> 8;
        // Current color B component
        u_int8_t B = currentColor & 0x0000FF;

        for (int j = 0; j < height; ++j) {
            // Write a pixel RGB24 to a file in BGR order
            fwrite(&B, 1, 1, bitmapFile);
            fwrite(&G, 1, 1, bitmapFile);
            fwrite(&R, 1, 1, bitmapFile);
        }
    }

    // Close file
    fclose(bitmapFile);
}

int main() {
    writeRGBToBmp("/Users/staff/Desktop/rainbow-700x700.bmp", 700, 700);
    return 0;
}

Check the generated BMP image

Congratulations! The picture viewing software recognizes our BMP picture, and the preview is normal!
BUT! What seems to be wrong?! Our rainbow is upside down!
Rainbow color, from top to bottom should be:
Red - > Orange - > Yellow - > Green - > Green - > Blue - > Purple
This picture is:
Purple - > Blue - > Green - > Green - > Yellow - > Orange - > Red

Handling picture inversion

The biHeight field in BitmapInfoHeader,
Bitmaps are scanned from bottom to top.
The biHeight is negative and the bitmap is scanned from top to bottom.
If the setting of this value does not match the scanning mode of the original bitmap file, the image display may be reversed.

<br/>

In the transformation code above, the BitmapInfoHeader section:

// infoHeader.biHeight = height;
infoHeader.biHeight = -height;

Congratulations!

Successful use of pixels to spell out a "real" picture!

Code:

rgb-to-bmp

Reference material:

Wikipedia-BMP

Bitmap (bmp) file format analysis

Converting RGB24 into BMP Image

Differences between RGB32 and RGB24

non-dword-aligned-pixel-to-dword-aligned-bitmap

generate-bmp-file-from-array-of-rgb-values

Is the content wrong? Contact author:

Topics: C++