Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BMP File line padding issue

So I'm trying to export a .bmp file in C++ code, and I have it working except for one major thing: line padding. I'm not 100% sure on how line padding works, but I know I need it. My algorithm works except for the padding, I manually added padding in a hex editor to my exported image and it worked. But how do I add padding? Here is what I have:

//Size of the file in bytes
    int fileSize = 54 + (3 * width * height);

    //The sections of the file
    unsigned char generalHeader[14] = {'B','M',0,0, 0,0,0,0, 0,0,54,0, 0,0};
    unsigned char DIBHeader[40]     = {40,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,24,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};
    unsigned char pixelArray[1000000];
    unsigned char bmpPad[3] = {0, 0, 0};

    //Set the binary portion of the generalHeader, mainly just file size
    generalHeader[2] = (unsigned char)(fileSize);
    generalHeader[3] = (unsigned char)(fileSize >> 8);
    generalHeader[4] = (unsigned char)(fileSize >> 16);
    generalHeader[5] = (unsigned char)(fileSize >> 24);

    //The binary variable portion of the DIB header
    DIBHeader[4]  = (unsigned char)(width);
    DIBHeader[5]  = (unsigned char)(width >> 8);
    DIBHeader[6]  = (unsigned char)(width >> 16);
    DIBHeader[7]  = (unsigned char)(width >> 24);
    DIBHeader[8]  = (unsigned char)(height);
    DIBHeader[9]  = (unsigned char)(height >> 8);
    DIBHeader[10] = (unsigned char)(height >> 16);
    DIBHeader[11] = (unsigned char)(height >> 24);

    //Loop through all width and height places to add all pixels


    int counter = 0;
    for(short j = height; j >= 0; j--)
    {
        for(short i = 0; i < width; i++)
        {
            //Add all 3 RGB values
            pixelArray[counter] = pixelColour[i][j].red;
            pixelArray[counter] = pixelColour[i][j].green;
            pixelArray[counter] = pixelColour[i][j].blue;
            counter++;
        }
    }

    //Open it
    ofstream fileWorking(fileName);

    //Write the sections
    fileWorking.write((const char*)generalHeader, 14);
    fileWorking.write((const char*)DIBHeader, 40);
    fileWorking.write((const char*)pixelArray, 3 * width * height);

    //NO MEMORY LEAKS 4 ME
    fileWorking.close();

pixelColour is of struct data type with the 3 colours, all type unsigned char. Any help is greatly appreciated!

like image 310
null Avatar asked Apr 03 '15 22:04

null


People also ask

What is padding in BMP?

The final part of the BMP file is the image data. The data is stored row by row with padding on the end of each row. The padding ensures the image rows are multiples of four.

Is BMP format compressed?

BMP files are uncompressed. If you want to compress a BMP file, you must do it manually.

What kind of compression does a BMP file use?

BMP images are generally uncompressed or compressed with a lossless compression method. The files can store two-dimensional digital images with both monochrome and color. Various Color Depths, alpha channels, color profiles and optional data compression are supported in this format.

Why is BMP so large?

BMP files are sometimes known as “true images” because they render each individual pixel within the file. They don't compress automatically. This makes them large — a collection of BMP files will rapidly consume lots of memory and space.


1 Answers

In your case, each row must be a multiple of 4 bytes (32 bits).

int pad = 0; // Set pad byte count per row to zero by default.
// Each row needs to be a multiple of 4 bytes.  
if ((width * 3) % 4 != 0) pad = 4 - ((width * 3) % 4); // 4 - remainder(width * 3 / 4).

Padding values can contain pretty much anything, but it is best to set them to 0. When you reach the end of writing each row, just write an additional pad number of zeroes (bytes) before writing the next row.

for(short j = height; j >= 0; j--) {
    for(short i = 0; i < width; i++) {
        //Add all 3 RGB values
        pixelArray[counter++] = pixelColour[i][j].red; // Need to advance counter.
        pixelArray[counter++] = pixelColour[i][j].green;
        pixelArray[counter++] = pixelColour[i][j].blue;
    }
    for (int padVal = 0; padVal < pad; padVal++) pixelArray[counter++] = 0; // Pad.
}

Finally, you need to write a larger file size:

fileWorking.write((const char*) pixelArray, (3 * width + pad) * height);
like image 56
Steven Hansen Avatar answered Sep 30 '22 00:09

Steven Hansen