0

I'm having some problems and cannot seem to find the bugs. The program seems to function correctly but cs50 check says that the file is too large. Would love to have someone to look at my code and help me with identifying the bug.

 // Copies a BMP file

#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 *number = argv[1];
    char *infile = argv[2];
    char *outfile = argv[3];

    int n = atoi(number);

    //validates n
    if(n < 0 || n > 100)
    {
        fprintf(stderr, "Usage: n must be a whole number between 1 and 100\n");
        return 5;
    }

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

    //crates new height and width
    long biWidthold = bi.biWidth;
    bi.biWidth *= n;
    bi.biHeight *= n;

    // determine padding for scanlines
    int paddingold = (4 - (biWidthold * sizeof(RGBTRIPLE)) % 4) % 4;
    int padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

    bi.biSizeImage = ((sizeof(RGBTRIPLE) * bi.biWidth) + padding) * abs(bi.biHeight);
    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);



    // iterate over infile's scanlines
    for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
    {

      for( int j = 0; j < n; j++)
      {

        // iterate over pixels in scanline
        for (int k = 0; k < biWidthold; k++)
        {
            // temporary storage
            RGBTRIPLE triple;

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

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

            for (int m = 0; m < padding; m++)
            {
              fputc(0x00, outptr);
            }

            if (j < n - 1)
              fseek(inptr, -(biWidthold * (int)sizeof(RGBTRIPLE)), SEEK_CUR);

      }


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

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // success
    return 0;
}

1 Answer 1

1

Have you looked at the actual hex data of the file instead of the image? When looking at the image, the header data (assuming it's correct) will only allow the display of the specified amount of data in the image. Any extra data at the end of the image will not be displayed.

When I looked at the actual file data, I saw that there are n times more rows of pixels than there should be, even though the image was correct. This tells me that the code is processing too many rows. So let's look at the relevant lines:

//crates new height and width
long biWidthold = bi.biWidth;
bi.biWidth *= n;
bi.biHeight *= n;

....

// iterate over infile's scanlines
for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)

The for loop sets the number of lines in the input file to be processed. The controlling variable in the for loop is bi.biHeight. Unfortunately, it has already been scaled up for the output file. That means that it is processing the number of lines in the output file, not the input file. That's why the code is processing too much data.

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

1
  • hi! ty ,managed to figure it out by myself in the end!
    – asaf
    Commented Aug 5, 2019 at 22:06

You must log in to answer this question.

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