1

Pulling my hair out a little.

My code compiles and works as expected as far as my eyes can see. However, it fails Check50 and has a runtime error:

resize.c:108:42: runtime error: unsigned integer overflow: 18446744073709551613 * 3 cannot be represented in type 'unsigned long'

Row 108 = fseek(inptr, -bi.biWidth * sizeof(RGBTRIPLE), SEEK_CUR);

If i run this against 'smiley.bmp' or 'small.bmp', the new image is indeed a larger version of the original despite this error. Please help!

When debugging, the error only seems to happen on the first pass (first line of the image i expect) so i've probably done a calculation wrong.

EDIT:

Fixed the error using ftell to get the current position but still fails the check50. I expect this is a header issue but can't figure out what.

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

#include "bmp.h"

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

    int factor = atoi(argv[1]);

    if (factor < 1 || factor > 100)
    {
        printf("Second argument must be between 1 and 100 inclusive\n");
        return 5;
    }

    // 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, bf_res;
    fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr);
    bf_res = bf;

    // read infile's BITMAPINFOHEADER
    BITMAPINFOHEADER bi, bi_res;
    fread(&bi, sizeof(BITMAPINFOHEADER), 1, inptr);
    bi_res = bi;

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

    // change width/height
    bi_res.biWidth = bi.biWidth * factor;
    bi_res.biHeight = bi.biHeight * factor;

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

    // change file sizes in headers
    bi_res.biSizeImage = (bi_res.biWidth * sizeof(RGBTRIPLE) + padding_res) * abs(bi_res.biHeight);
    bf_res.bfSize = bf.bfSize - bi.biSizeImage + bi_res.biSizeImage;

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

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

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

        for (int f = 0; f < factor; f++)
        {
            fseek(inptr, pos, SEEK_SET);
            // 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 k = 0; k < factor; k++)
                    fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
            }

            // Add padding for resized image
            for (int k = 0; k < padding_res; k++)
            {
                fputc(0x00, outptr);
            }   
        }
        // skip over padding, if any
            fseek(inptr, padding, SEEK_CUR);
    }

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // that's all folks
    return 0;
}

Thanks!

4
  • I have the same problem and in the same place. Oct 12, 2016 at 16:39
  • If you're talking about the runtime error, i've already answered that and modified my code above :)
    – Ian Grover
    Oct 12, 2016 at 16:40
  • What is check50 saying?
    – Andy Alt
    Oct 12, 2016 at 18:39
  • - 0 Running... clang -o resize resize.c -lcs50 -lm. ✔ - 1 Expecting an exit code of 0. ✔ - 2 1.bmp. ✔ - 3 Running... ./resize 2 infile.bmp outfile.bmp. ✔ - 4 Expecting an exit code of 0. ✔ - 5 Checking for file outfile.bmp. ✔ - 6 TODO. --- Looks like it's failing to find the outfile.bmp but this should be working fine as the file is always created when i test it.
    – Ian Grover
    Oct 12, 2016 at 19:13

1 Answer 1

0

Found the issue

for (int i = 0, biHeight = abs(bi_res.biHeight); i < biHeight; i++)

I'm using the wrong height value. Changed to:

for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)

All checks passed :D

You must log in to answer this question.

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