0

I am doing CS50x and just finished resize.c; I checked it with various values of enlargement and it returns the correct results. I compared this with staff solution, using diff, peek, and xxd, my results match the staff solution. However, check50 is giving showing that my solution, save for the first two criteria. I ran update50 as well and it is still giving me a problem. So far the headers are correct and I can't seem to locate any extra pixels. Can someone please look at my code and help me because this is quite frustrating.

/**
* copy.c
*
* Computer Science 50
* Problem Set 4
*
* Copies a BMP piece by piece, just because.
*/

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

#include "bmp.h"

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

// remember filenames
char* factor = argv[1];
char* infile = argv[2];
char* outfile = argv[3];
int n = atoi(factor);
if (n < 1 || n > 100)
{
    printf("Please enter a scale factor between one and hundred.");
    return 1;
} 

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

// 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;
}
//"save" old variables
int height = abs(bi.biHeight);
int width = bi.biWidth;
int padding_a = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

//new variables
bi.biHeight = bi.biHeight * n;
bi.biWidth = bi.biWidth * n;
int padding_b = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
bi.biSizeImage = (((bi.biWidth) * abs(bi.biHeight)) * 3) + (padding_b * 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);

// reads each row
for (int i = 0; i < height; i++)
{
    //prints each row n times
    for (int j = 0; j < n; j++)
    {
        //read each pixel
        for (int k = 0; k < width; k++)
                    {
             // temporary storage
            RGBTRIPLE triple;

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


            //prints each pixel n times

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

        // places the new padding at the end of each line
        for (int m = 0 ; m < padding_b; m++)
        {
            fputc(0x00, outptr);
        }
        //goes back to the beginning of the orignal line
        fseek(inptr,(-1 * width * sizeof(RGBTRIPLE)), SEEK_CUR);

    }
    fseek(inptr, sizeof(RGBTRIPLE)*(width + padding_a), SEEK_CUR);  
}
/** 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
        fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
    }


    fseek(inptr, padding, SEEK_CUR);

    // then add it back (to demonstrate how)
    for (int k = 0; k < padding; k++)
    {
        fputc(0x00, outptr);
    }
}
*/
// close infile
fclose(inptr);

// close outfile
fclose(outptr);

// that's all folks
return 0;
}

*NOTE the greyed out code is from copy.c which I used for easy reference.

1
  • If there is something wrong can someone please tell me which aspect I messed up? Nov 4 '15 at 10:00
0

Here's your problem:

    fseek(inptr, sizeof(RGBTRIPLE)*(width + padding_a), SEEK_CUR); 

You want to reset to the beginning of the next line, but you're going too far. To illustrate, apply the distributive property of multiplication and you will get the following:

sizeof(RGBTRIPLE)*(width + padding_a) = 
(sizeof(RGBTRIPLE) * width)  +  (sizeof(RGBTRIPLE) * padding_a )

That's too much padding! There should be only one count of padding in the move.

Amazing how the incorrect placement of parentheses can break a perfectly good formula. ;-)

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

3
  • I can't thank you enough. I went over the code more times than I could count :) Well I guess I have to triple check the parentheses next time!XD Nov 4 '15 at 17:17
  • How about thanking me by clicking on the check mark to accept the answer? Otherwise it will linger in the unanswered question pool forever,
    – Cliff B
    Nov 15 '15 at 22:46
  • Oops! sorry, i forgot Dec 28 '15 at 18:53
1

I think the problem lies with your nested structure. The way you've structured results in reading and storing each pixel n number of times, when you should only need to read each pixel once, and then print it n number of times.

I would suggest restructuring your nested loops so you can: 1- read every pixel in the scan line and store it in a temporary struct. 2- write each pixel n number of times 3- add padding 4- Repeat steps 3&4 by n amount of times. Restructuring will also allow you to lose the fseek function that resets your pointer to the beginning of each line.

Also, check the way you're skipping padding when you read each line. If you set your padding_a variable correctly then the fseek function called at the end will result in skipping extra bytes. Hope this helps. gl

4
  • But I am only reading each pixel once. After reading the pixel, I print it n times, after which I read the next pixel. When the line is done I add padding, then proceed to print each line again. At least thats what I think it's doing. Or is it doing something I don't understand. BTW the skip over padding comment is wrong, plz ignore it. Nov 4 '15 at 15:59
  • Well I'm not sure what check 50 is telling you, that could be helpful, the original comment is not very explicit. Your solutions relies on reading each of the original pixels every time, for every line you're scaling up. I found that the alternative, to read all pixels per line and store them in an array for reproduction later on was more simple. Nov 4 '15 at 16:36
  • :) 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 sandbox.cs50.net/checks/b19452a3eefe4eb9bfd5e768d0c053bd Nov 4 '15 at 16:38
  • I tried the same program on small.bmp and the resized image has a black center and a small black square in the bottom right corner. Other than that large.bmp and smiley.bmp are fine. Nov 4 '15 at 16:40

You must log in to answer this question.

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