1

I think I'm having a lot of the same issues that some of my other classmates are having with resize.c, so was wondering if you guys could take a look at my code and help me see where I'm messing up. Per the title, my code works fine when the output file requires no padding. But when it does (i.e. when I try to resize "small.bmp" by 3x), it breaks. Is it an issue with how I'm going about pushing the padding?

/**
 * resize.c
 *
 * Copies a BMP piece by piece to resize using padding.
 */

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

#include "bmp.h"

int main(int argc, char* argv[])
{

    // ensure proper usage
    if (argc != 4 || atoi(argv[1]) > 100 || atoi(argv[1]) <= 0)
    {
        printf("Usage: ./resize (n<=100) infile outfile\n");
        return 1;
    }

    // remember filenames
    char* infile = argv[2];
    char* outfile = argv[3];

    // open input file 
    FILE* inptr = fopen(infile, "r");
    if (inptr == NULL)
    {
        printf("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;
    fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr);

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

    int inputPadding =  (4 - ((bi.biWidth * sizeof(RGBTRIPLE)) % 4)) % 4;
    int outputPadding =  (4 - ((bi.biWidth * atoi(argv[1]) * sizeof(RGBTRIPLE)) % 4)) % 4;

    // printf("Input Padding: %i, Output Padding: %i\n", inputPadding, outputPadding);

    // 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;
    }

    // reset header values for writing to output file
    bi.biHeight = bi.biHeight * atoi(argv[1]);
    bi.biWidth = bi.biWidth * atoi(argv[1]);
    bi.biSizeImage = (bi.biWidth * sizeof(RGBTRIPLE) + outputPadding) * abs(bi.biHeight);
    bf.bfSize = bi.biSizeImage + 54;

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

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

    // create data structure for triples
    RGBTRIPLE trip[abs(bi.biWidth)/atoi(argv[1])];
    int spot = 0;

    // iterate over infile's scanlines
    for (int i = 0, biHeight = abs(bi.biHeight/atoi(argv[1])); i < biHeight; i++)
    {
        // iterate over pixels in scanline
        for (int j = 0; j < bi.biWidth/atoi(argv[1]); j++)
        {
            // read RGB triple from infile
            fread(&trip[j], sizeof(RGBTRIPLE), 1, inptr);
        }

        // write RGB triple to outfile
        for(int j = 0; j < bi.biWidth; j++)
        {
            for(int w = 0; w < atoi(argv[1]); w++)
            {
                spot = j % (bi.biWidth/atoi(argv[1]));
                fwrite(&trip[spot], sizeof(RGBTRIPLE), 1, outptr);
            }
        }
        for (int k = 0; k < outputPadding; k++)
        {
            fputc(0x00, outptr);
        }
        // skip over padding, if any
        fseek(inptr, inputPadding, SEEK_CUR);
    }
    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // that's all folks
    return 0;
}

Current check50 status:

:) resize.c and bmp.h exist
:) resize.c compiles
:) doesn't resize 1x1-pixel BMP when n is 1
:( resizes 1x1-pixel BMP to 2x2 correctly when n is 2
:( resizes 1x1-pixel BMP to 3x3 correctly when n is 3
:) resizes 1x1-pixel BMP to 4x4 correctly when n is 4
:( resizes 1x1-pixel BMP to 5x5 correctly when n is 5
:) resizes 2x2-pixel BMP to 4x4 correctly when n is 2

2

You should be capable of figuring that out using the different tools that provided to you (e.g., gdb, peek, the staff's solution, etc.).

Let's see what should happen if we resize a 1x1 BMP by a factor of 2. Think of a * as a pixel and a 0 as a padding byte.

*0 // this is a 1x1

Re-sizing this by a factor of 2 should result in this

**00
**00

Now let's see what your program actually does; particularly, the re-sizing part. The thing is that biHeight/atoi(argv[1]) and biWidth/atoi(argv[1]) are 2/2 and 2/2 or 1 and 1 respectively. So your loops that iterate over the height and the width of the BMP each iterate only one time. So you basically get something like this

****00

rather than the one that you should get as shown above.

| improve this answer | |
  • Thanks Kareem - I realized that I ended up overcomplicating this because of those biHeight/atoi(argv[1]) lines, so I broke it down further using the steps you detailed to solve. Appreciate your help! – jayrav13 Feb 22 '15 at 19:09

You must log in to answer this question.

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