0

I just cannot stop getting funky different colors when I resize, and I see it must be some padding issue. I used the specs and peek to compare my file student.bmp with the staff.bmp. It shows in red that the bfSize is different.

~/workspace/pset4/resize/ $ ~cs50/pset4/peek student.bmp staff.bmp offset type name argv[1] argv[2] 0 WORD bfType 4d42 4d42 2 DWORD bfSize 0000005a 000001e6

Wasn't the bfSize set already in the struct BITMAPFILEHEADER bf? I set a new newbf.bfSize, but I didn't change the old one.

Here is my code. How can I know what's wrong??

// Copies a BMP file

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

#include "bmp.h"

int main(int argc, char *argv[])
{
    //store number by which to resize
    float factor = atof(argv[1]);
    // remember filenames
    char *infile = argv[2];
    char *outfile = argv[3];

    // ensure proper usage
    if (argc != 4 || factor < 1 || factor > 100)
    {
        fprintf(stderr, "Usage: resize n infile outfile\n");
        return 1;
    }

    // open input file
    FILE *inptr = fopen(infile, "r");
    if (inptr == NULL)
    {
        fprintf(stderr, "Could not open %s.\n", infile);
        return 2;
    }

    // open output file
    FILE *outptr = fopen(outfile, "w");
    if (outptr == NULL)
    {
        fclose(inptr);
        fprintf(stderr, "Could not create %s.\n", outfile);
        return 3;
    }

    // read infile's BITMAPFILEHEADER
    BITMAPFILEHEADER bf, newbf;
    fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr);

    // read infile's BITMAPINFOHEADER
    BITMAPINFOHEADER bi, newbi;
    fread(&bi, sizeof(BITMAPINFOHEADER), 1, inptr);

    //swap (store) infile's file header and info header as outfiles's headers
    newbf = bf;
    newbi = bi;

    //update width and height in info header
    newbi.biWidth = bi.biWidth * factor;
    newbi.biHeight = bi.biHeight * factor;

    // ensure infile is (likely) a 24-bit uncompressed BMP 4.0
    if (bf.bfType != 0x4d42 || bf.bfOffBits != 54 || bi.biSize != 40 ||
        bi.biBitCount != 24 || bi.biCompression != 0)
    {
        fclose(outptr);
        fclose(inptr);
        fprintf(stderr, "Unsupported file format.\n");
        return 4;
    }

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

    // store new padding for scanlines
    int newpadding = (4 - (newbi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

    // update file size in file header
    // bf.bfSize = 54 + image_size;
    // bfSize is always 54 + the size of the image
    //54 is the size of the 2 headers
    newbf.bfSize = 54 + newbi.biSizeImage;
    //reddit bi.biSizeImage = lines * linelength
    //linelength = (3 * nopixels) + padding
    // lines * (3 * nopixels) + padding)

    //update image size in info header
    //orig. formula - bi.biSizeImage = ((sizeof(RGBTRIPLE)*bi.biWidth) + newpadding) * abs(bi.biHeight);
    //bi.biSizeImage = (bi.biWidth * 3 * abs(bi.biHeight)) + (padding * abs(bi.biHeight));
    //check
    newbi.biSizeImage = ((newbi.biWidth * 3 * abs(newbi.biHeight) + (newpadding * abs(newbi.biHeight))));

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

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

    // iterate over infile's scanlines
    for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
    {
        // 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
            //write each row
            for (int k = 0; k < factor; k++)
            {
                //write each pixel
                for (int pixel = 0; pixel < factor; pixel++)
                {
                    fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
                    //skip over padding in old file, if any
                    fseek(inptr, padding, SEEK_CUR);
                    //add padding to new file
                    for (int p = 0; p < newpadding; p++)
                    {
                        fputc(0x00, outptr);
                    }
                }
            }
        }
    }

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // success
    return 0;
}

1 Answer 1

0

The header problem is simple. bfSize is dependent on biSizeImage. Perhaps bfSize should be calculated after biSizeIMage?

The image data is another story. The nested for loops are a convoluted mess. I wasn't able to exactly determine what they were doing, but they are definitely adding padding after every pixel and are producing too much output data.

The padding should only be added at the end of each line. It might also help you to just work on getting the horizontal scaling right at first, and then work on vertical. Use a scaling of 1 and then 2 to get the horizontal right, and then work on vertical. Finally, I'd suggest starting over on the for loops. Don't try to correct the existing code. I think it'll just be too confusing. Better to start clean on this one.

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

You must log in to answer this question.

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