BMP File line padding issue
Asked Answered
D

1

7

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!

Diggs answered 3/4, 2015 at 22:45 Comment(0)
A
7

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);
Alicea answered 3/4, 2015 at 23:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.