0

output from resize.c

Hello everyone. I hope you are well.

I am having a bit of a tough time with the resize portion of problem set 4 and I feel I am super close. When I run my program (./resize 4 small.bmp large.bmp), my green square stretches out as per the attached image. Would anyone here be able to give me some pointers in the right direction please?

Here's my code:

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

#include "bmp.h"

int main(int argc, char* argv[])
{
    // ensure proper usage
    if (argc != 4)
    {
    printf("Usage: ./copy infile outfile\n");
    return 0;
}

// remember filenames
int resizeFactor = atoi(argv[1]);
char* infile = argv[2];
char* outfile = argv[3];

if (resizeFactor < 0 || resizeFactor > 100)
{
    return 0;
}

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

printf("biSizeImage before: %i\n", bi.biSizeImage);
printf("file size before: %i\n", bf.bfSize);

bi.biWidth *= resizeFactor;
bi.biHeight *= resizeFactor;

printf("biWidth: %i\n", bi.biWidth);
printf("biHeight: %i\n", bi.biHeight);

// determine padding for scanlines
// int overshoot = (bi.biWidth * sizeof(RGBTRIPLE)) % 4;
// int padding = overshoot > 0 ? 4 - overshoot: 0;
int padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

bi.biSizeImage = (bi.biWidth * abs(bi.biHeight)) + padding;

printf("\npadding: %i\n", padding);

printf("biSizeImage after: %i\n", bi.biSizeImage);
printf("file size after: %i\n", bf.bfSize);

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

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

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

/* plan to iterate through the pixels:
* read the file in
* for each row of pixels
*   copy each pixel n times over
* add any padding if required
*/

// iterate over infile's scanlines
for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
{
    for (int l = 0; l < resizeFactor; l++)
    {
        // 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
            for (int h = 0; h < bi.biWidth; h++)
            {
                fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
            }
        }

        // if we need to add padding, then add it
        if (padding != 0)
        {
            for (int k = 0; k < padding; k++)
            {
                fputc(0x00, outptr);
            }
        }
        // otherwise skip the padding
        else{
            fseek(inptr, padding, SEEK_CUR);
        }
        fseek(outptr, -(bi.biWidth + padding), SEEK_CUR);
    }

}
// close infile
fclose(inptr);

// close outfile
fclose(outptr);

// that's all folks
return 0;
}
0

There are several issues with the code. More than one header value is not calculated correctly. The padding for both the input and output files need to be calculated independently. When adding padding, there's no need to decide if it is needed. If the padding is correctly calculated, it will be calculated as 0 when appropriate. There may be other issues, but this will get you started.

My advice is to start with ./resize 1 small.bmp s2.bmp. The output file should be identical to the input file. Using the peek tool, compare the headers. Fix any problems there first. Once the headers are correct, compare the image data using the xxd tool, and fix any image data issues. Only after it works for a resize factor of 1, move on to a resize of 2 and repeat the whole process. Use the staff example to generate an output file to compare against.

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

2
  • Update: I have done it. The image now upscales as and shows properly. I ran it through check50 and all the tests went green. Here's how I did it: I changed my formula for biOut.biSizeImage and bfOut.bfSize. Additionally, I calculated the padding for the infile and the outfile independently. Same with the bfSize and the biSizeImage. I also changed the comparison that I am doing in the for loops (i.e. the second argument of the for loop). I won't go through the specifics (so I am not breaching the academic honesty rules) but thanks for everyone's help. Oct 1 '16 at 22:14
  • This is a great answer. The headers are completely the same but the diff command says they differ - what shall I go by? Jan 5 '17 at 15:12
0

I'm struggling with resize too! Two issues:

1) If you look at copy.c, the code skips over the padding without an else statement, because if padding is 0, then the file pointer would not move.

2) Your fseek is moving the wrong file pointer. Remember you are reading from the infile and writing to the outfile.

Hope this helps!!

1
  • Thanks for your help. After implementing both of your suggestions I am still no closer. Sep 28 '16 at 17:25

You must log in to answer this question.

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