0

The bmp images looks pretty much alike with the staff's bmp when there is no padding. But when I use a factor of 3, the image shows random colors, even when xxd padding seems to be ok.

I also checked the headers with peek and they're not the problem. I can't find what's wrong with my program, any ideas?

enter image description here

enter image description here

BITMAPFILEHEADER bfOut = bf;
BITMAPINFOHEADER biOut = bi;


// determine padding for scanlines
int padding =  (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
int newPadding = ((4 - (bi.biWidth * n) % 4) % 4) * sizeof(RGBTRIPLE);

//change values and write outfile's BITMAPFILEHEADER
biOut.biWidth = n * bi.biWidth;
biOut.biHeight = n * bi.biHeight;
bfOut.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + ((newPadding + (bi.biWidth * n)) * (abs(n * bi.biHeight)) * (sizeof(RGBTRIPLE)));

fwrite(&bfOut, sizeof(BITMAPFILEHEADER), 1, outptr);

//change values and write for outfile's BITMAPINFOHEADER    

biOut.biSizeImage = ((newPadding + (bi.biWidth * n)) * (abs(n * bi.biHeight)) * (sizeof(RGBTRIPLE)));

fwrite(&biOut, sizeof(BITMAPINFOHEADER), 1, outptr);


// iterate over infile's scanlines
for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
{
    //for n times
    for (int z = 0; z < n; z++)
    {
        // iterate over pixels in scanline
        for (int j = 0; j < bi.biWidth; j++)
        {
            // temporary storage
            RGBTRIPLE triple;

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

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

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

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

            fseek(inptr, -((bi.biWidth * sizeof(RGBTRIPLE)) + padding),  SEEK_CUR);
    }

    fseek(inptr, (bi.biWidth * sizeof(RGBTRIPLE)) + padding,  SEEK_CUR);

}

// close infile
fclose(inptr);

// close outfile
fclose(outptr);

// that's all folks
return 0;

}

  • Are you sure you xxd'd the right file? The staff.bmp image you have included the snapshot of should contain each of the following colors. [ Blue : ff0000, Green : 00ff00, Red : 0000ff, Black : 000000, White : ffffff ] In the command prompt / terminal you showed, I only see green and white? – Sam Gerber Sep 28 '15 at 3:11
1

Here's probably your biggest problem:

int padding =  (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
int newPadding = ((4 - (bi.biWidth * n) % 4) % 4) * sizeof(RGBTRIPLE);

Your calculation for the new padding is wrong. biWidth is the number of PIXELS in a given line, but you're calculating the padding in bytes. To get the correct padding, you need the correct width in bytes BEFORE applying the modulo operations.

But the problem doesn't stop there. You have made the same mistake in calculating two of the header values. In short, you should never multiply any padding value by sizeof(RGBTRIPLE).

I suggest you run the following and then compare the two bmp files. ./resize small.bmp s2.bmp After creating s2.bmp, compare the headers using peek and then (after you fix the padding issue), compare the binary values using xxd.

If this answers your question, please click on the check to accept. Let's keep up on forum housekeeping. ;-)

| improve this answer | |
  • Thaks a lot! It took me a while to understand exactly what was the error in bfSize and biSizeImage , but now I see it so much clearly. That solved the problem, now I have all smiley faces :) – Belu Sep 28 '15 at 4:23
2

These are very different, and are likely the cause of the problem. Do you understand the formula?

int padding =  (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
int newPadding = ((4 - (bi.biWidth * n) % 4) % 4) * sizeof(RGBTRIPLE);

...the scanline is "padded" with as many zeroes as it takes to extend the scanline’s length to a multiple of 4. - http://cdn.cs50.net/2015/x/psets/4/pset4/pset4.pdf

So let's tease apart your equation:

padding =  (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4
  1. sizeof(RGBTRIPLE) is the number of BYTES in a pixel. If we have variables measured in PIXELS, we can multiply by this to get the variable in BYTES
  2. (bi.biWidth * sizeof(RGBTRIPLE)) this converts biWidth from PIXELS to BYTES
  3. (bi.biWidth * sizeof(RGBTRIPLE)) % 4 tells us how many BYTES wider than a multiple of four BYTES the image is. Possible values:

    • 0 -> the image's width in BYTES is a multiple of four
    • 1 -> the image's width in BYTES is one greater than a multiple of four
    • 2 -> the image's width in BYTES is two greater than a multiple of four
    • 3 -> the image's width in BYTES is three greater than a multiple of four
  4. (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) tells us how many more BYTES we'll need to add to reach the next multiple of four. Possible values:

    • 4-0 = 4 -> the image is four BYTES short of being a multiple of four???
    • 4-1 = 3 -> the image is three BYTES short of being a multiple of four
    • 4-2 = 2 -> the image is two BYTES short of being a multiple of four
    • 4-3 = 1 -> the image is one BYTES short of being a multiple of four
  5. (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4 this one is a bit tricky and is just meant to change the first possible value from 4 to 0.Possible values:

    • 4%4 = 0 -> the image is zero BYTES short of being a multiple of four!!!
    • 4%3 = 3 -> the image is three BYTES short of being a multiple of four
    • 4%2 = 2 -> the image is two BYTES short of being a multiple of four
    • 4%1 = 1 -> the image is one BYTES short of being a multiple of four

So in your formula for newPadding, things are in a different order, and you're essentially working through all the math with PIXELS, and then converting to BYTES at the end, which doesn't work.

You'll also run into trouble in both your ..Size.. calculations for the new header. Padding is in BYTES, so you don't need to multiply it by the PIXEL to BYTE converter sizeof(RGBTRIPLE).

I think fixing those three lines should do the trick! Good luck!

| improve this answer | |
  • Thank you so much! That was very helpful for understanding the formula. After changing that the image showed perfectly, however I still had errors in my bfSize and biSizeImage that I already corrected. Now I have all smiley faces :) ...Sorry for bad English – Belu Sep 28 '15 at 4:18

You must log in to answer this question.

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