0

I've finally managed to get the new headers to write correctly, but the BMP itself is not being created properly. Black pixels (0x000000) are appearing in my output files and I'm not sure where my program is getting this information from, since the original small.bmp doesn't have any 0x000000 pixels.

In my program, I have bi_in and bf_in that correspond to the infile, and bi_out and bf_out for the outfile.

// determine padding for scanlines
int padding_in = (4 - (bi_in.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

// create the outfile headers
BITMAPFILEHEADER bf_out;
bf_out = bf_in;

BITMAPINFOHEADER bi_out;
bi_out = bi_in;
bi_out.biWidth = bi_in.biWidth * factor;
bi_out.biHeight = bi_in.biHeight * factor;

// determine padding for scanlines
int padding_out = (4 - (bi_out.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

bi_out.biSizeImage = (bi_out.biWidth * sizeof(RGBTRIPLE) + padding_out) * abs(bi_out.biHeight);

bf_out.bfSize = bi_out.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

// write outfile's BITMAPFILEHEADER
fwrite(&bf_out, sizeof(BITMAPFILEHEADER), 1, outptr);

// write outfile's BITMAPINFOHEADER
fwrite(&bi_out, sizeof(BITMAPINFOHEADER), 1, outptr);

// iterate over infile's scanlines
for (int i = 0, biHeight = abs(bi_in.biHeight); i < biHeight; i++)
{
    for (int l = 0; l < factor; l++)
    {
        if (l != 0)
        {
            fseek(inptr, -(bi_in.biWidth + padding_in), SEEK_CUR);
        }

        // iterate over pixels in scanline
        for (int j = 0; j < bi_in.biWidth; j++)
        {
            // temporary storage
            RGBTRIPLE triple;

            // read RGB triple from infile
            fread(&triple, sizeof(RGBTRIPLE), 1, inptr);

            for (int k = 0; k < factor; k++)
            {
                // write RGB triple to outfile
                fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
            }
        }

        // skip over padding, if any
        fseek(inptr, padding_in, SEEK_CUR);

        // then add it back (to demonstrate how)
        for (int k = 0; k < padding_out; k++)
        {
            fputc(0x00, outptr);
        } 
    }
}
1

Per fseek's man page

int fseek(FILE *stream, long offset, int whence);

The fseek() function sets the file position indicator for the stream pointed to by stream. The new position, measured in bytes, is obtained by adding offset bytes to the position specified by whence.

It turns out that you're not seeking back the correct number of bytes in

fseek(inptr, -(bi_in.biWidth + padding_in), SEEK_CUR);
4
  • That worked, thanks! I was sure I tried that exact fix before but I guess something else was going on at that time. The whole measuring by bytes thing is still a little bit hazy in my mind, but I guess this means the padding var is counting by bytes where the biWidth is counting by pixels? Why are they different? Apr 5 '15 at 9:23
  • That's right! According to MSDN, biWidth is the width of the BMP in pixels. We know each pixel is an RGBTRIPLE and each RGBTRIPLE is 3 bytes long. When you calculate the padding, you calculate the number of bytes (not pixels) that should be added to make the size of a scanline (the size of the pixels in a scanline) + the padding a multiple of 4.
    – kzidane
    Apr 5 '15 at 9:44
  • @GlennM.Davis ^
    – kzidane
    Apr 5 '15 at 9:50
  • Got it, thanks! Apr 5 '15 at 13:17

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .