2

I have been stuck on the resize pset for a few days now. I have looked at all questions on here and reddit but just can't figure it out. When I do the peek, the headers seem consistent with the staff implementation. I have gone line by line using GDB but still don't see where the problems are. I have come to a bit of a dead end, I have made so many changes to my code to try and get it working I don't know what to try next. It is now showing as compiling but nothing is else is working as per Check50. If anyone could be point me in the general direction of the parts of the code that I should be focusing on I would greatly appreciate. Apologies if my query is similar to others on the forum but I don't know enough to spot it!

    int main(int argc, char* argv[])
    {
        // takes n and converts to int
        int n = atoi(argv[1]);

        // ensure proper usage
        if (argc != 4 || n < 1 || n > 100)
        {
            printf("Usage: ./resize n(must be in the range 1 - 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);


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


        //Create header files for output file
        BITMAPFILEHEADER bf_out = bf;   
        BITMAPINFOHEADER bi_out = bi; 

        //Update the output file headers
        bi_out.biWidth= bi.biWidth * n;
        bi_out.biHeight= bi.biHeight * n;


        // determine padding for old and new scanlines
        int old_padding =  (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
        int new_padding =  (4 - (bi_out.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

        // calculates new size of image 
        bi_out.biSizeImage = (bi_out.biWidth + new_padding) * abs(bi_out.biHeight) * sizeof(RGBTRIPLE);
        bf_out.bfSize = bi_out.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

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

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



        // iterate over infile's scanline
        for (int i = 0, h = abs(bi.biHeight); i < h; i++)
        {
            // do this factor number of times 
            for (int m = 0; m < n; m++)
            {
                //iterate through the pixels
                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 z = 0; z < n; z++)
                        {
                            fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
                        }

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

                        // add in new padding if required
                        for (int k = 0; k < new_padding; k++)
                        {
                            fputc(0x00, outptr);
                        }        
                } 

            }
        // close infile
        fclose(inptr);

        // close outfile
        fclose(outptr);

        // that's all folks
        return 0;

    }

1 Answer 1

3

You have two main problems. First, you have an error in your header. Second, you have overlooked a step in scaling the image.

Let's start with the header. If you ran small.bmp through your program with a scaling factor of 1, it should generate an exact copy of the input file. However, if you checked with peek, you would see that biSizeImage and bfSize are wrong. The latter is wrong because it depends on the former. Look at this line:

bi_out.biSizeImage = (bi_out.biWidth + new_padding) * abs(bi_out.biHeight)
     * sizeof(RGBTRIPLE);

Your error is multiplying everything in the calculation by sizeof(RGBTRIPLE). The purpose of multiplying by sizeof(RGBTRIPLE) is to convert something that counts pixels into bytes - biWidth. BUT, padding is not an RGBTRIPLE, it is measured in bytes already. Fix this and bfSize should be correct too.

Next, you have a scaling problem. Scaling by only 1 works (once header is fixed), but not when you go larger. You have the right idea that you need to scale each line up and then add padding, and then do it again n times, but you forgot that you need to go back to the start of the line of pixels in the input file on each pass.

Of course, once you fix this, remember to go to the next line after you've made enough copies of the current line in the output file. Also make sure that you pay attention to position and proper output of padding in both input and output files. ;-)

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

2
  • Thank you so much Cliff B. That was a great help. Out of interest, when I ran the peep instructions as per the pset for staff.bmp and student.bmp, I was always getting two columns of green for both implementations. That made me think my headers were ok although clearly they were not. What should I be looking out for when I run peep?
    – Breninio
    Commented Sep 22, 2015 at 8:28
  • I don't know what you wer using for input to peep, but it is possible that some input files would look correct as you commented, but another set of input files would not. If your program were scaling to 1 correctly, or if you were testing with files that had no padding when you aren't handling padding correctly, this can happen. Finally, if the headers are right but the image is wrong, peek won't show that.
    – Cliff B
    Commented Oct 13, 2015 at 18:18

You must log in to answer this question.

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