0

Can someone please review this code for Resize Less pset. It seems to me that it is functioning correctly and resizing the images appropriately. However, I am failing all of the checks when is submit it using Submit50. The error is stating that "Image has more bytes than expected". I've spent many hours going over and trying different things, I am just lost trying to figure out what is wrong with it. It seems to be working fine for me.

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

#include "bmp.h"

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

    // remember filenames
    char *infile = argv[2];
    char *outfile = argv[3];
    int n = atoi(argv[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;
    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;
    }

    //update info headers
    int width = bi.biWidth;
    int height = bi.biHeight;
    int n_height = height * n;
    int n_width = width * n;

    // determine padding for scanlines
    int n_padding = (4 - (n_width * sizeof(RGBTRIPLE)) % 4) % 4;
    int padding = (4 - (width * sizeof(RGBTRIPLE)) % 4) % 4;

    //update bi and bf
    bi.biHeight = n_height;
    bi.biWidth = n_width;
    bi.biSizeImage = ((sizeof(RGBTRIPLE) * n_width) + n_padding) * abs(n_height);
    bf.bfSize = bi.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

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

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

    RGBTRIPLE scanline[n_width * sizeof(RGBTRIPLE)];


    // iterate over infile's scanlines
    for (int i = 0, biHeight = abs(height); i < biHeight; i++)
    {
        //iterate for og file lines * n
        for (int j = 0; j < n; j++)
        {
            // iterate over pixels in scanline
            for (int k = 0; k < width; k++)
            {
                // temporary storage
                RGBTRIPLE triple;

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

                for (int l = 0; l < n; l++)
                {
                    scanline[(k * n) + l] = triple;
                }
            }

            fseek(inptr, padding, SEEK_CUR);

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

                // then add it back (to demonstrate how)
                for (int k = 0; k < n_padding; k++)
                {
                    fputc(0x00, outptr);
                }
            }
        }
    }

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // success
    return 0;
}
2

I would wager that you looked at the images but not at the raw data in the files. Since the header is correct, it tells any bmp viewer to display the amount of data that should be in the image, but if there's any additional data, it won't be displayed. If you had looked at the raw data, you would see that for a scaling factor greater than 1, there's extra data. For example, if n=2, and the original file had 3 rows, the output file would have 12 rows when it should only have 6.

The problem is that the scaling is being applied twice. It's a subtle logic error. Here's how it's happening. The code prints each line n times by creating a scaled up line in a buffer and printing it out n times. BUT, it also processed that entire code block again n times, thanks to the for(j) loop. When the end of the input file is found, the code just keeps printing out copies of the last contents of the buffer, thus adding double the image data.

I'll leave it to you to fix. It's an easy fix. ;-)

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

1
  • Oh wow, you're right it was an easy fix. Just removing the extra J loop worked for me. Thanks for your help and thorough explanation! May 1 '19 at 14:06

You must log in to answer this question.

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