0

my resize programm in pset4 has an error:

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

Here is my code:

/**
* 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) // change for 4 command-line arguments
{
    printf("Usage: ./resize n infile outfile\n");
    return 1;
}

// remember filenames
int sf = atoi(argv[1]); // size factor for resizing
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 structs that will be written in output file
BITMAPFILEHEADER bf_out;
bf_out = bf;

BITMAPINFOHEADER bi_out;
bi_out = bi;

bi_out.biWidth = bi.biWidth * sf;
bi_out.biHeight = bi.biHeight * sf;

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

// determine padding for scanlines for input file
int padding_inp =  (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

/**
* See http://cs50.stackexchange.com/questions/14016/pset4-resize-c-bfsize-bisizeimage-formulas for understand of values in BITMAPINFOHEADER
* */

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

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 scanlines
for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
{

    //iterate sf times through scanlines
    for (int r = 0; r < sf; r++ )
    {
        // 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);

            // iterate sf times through pixels

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

        }

        // back to the start of the scanline
        fseek(inptr, -bi.biWidth * sizeof(RGBTRIPLE), SEEK_CUR);

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

    //go to the next row
    fseek(inptr, bi.biWidth * sizeof(RGBTRIPLE)  + padding_inp, SEEK_CUR);


}

// close infile
fclose(inptr);

// close outfile
fclose(outptr);

// that's all folks
return 0;
}

According to the error message in the line 125 there is a proble with int "overflowing"

Line 125:

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

I really don't understand where is here so big number as 18446744073709551613 ???? I think this problem is related with structure of fsee() function, but don't know more(((

4

You are subtracting from bi.biWidth on line 125. Since bi.biWidth is an unsigned long, it cannot contain negative values (-1 and so on), instead it's capacity to store positive values is doubled. So by subtracting you are just setting bi.biWidth to what it would be if it were a signed long, but since it's unsigned you just get a very, very large number.

An integer looks like this in memory: 00000000. By subtracting 1 (-1) from this, you will get 11111111 which is 4294967295 unsigned, or -1 signed.


FIX:

Declare a var that can store negative values: long offset = bi.biWidth * sizeof(RGBTRIPLE); Then to navigate with fseek(): fseek(inptr, -offset, SEEK_CUR);

Note: Do NOT change anything in bmp.h! Just use a new variable that is signed.

  • Could you please explaine me why I substracting from bi.biWidth? What should I do to just put evaluted value in fseek()? int width = -1*bi.biWidth * sizeof(RGBTRIPLE); // back to the start of the scanline fseek(inptr, width, SEEK_CUR); Above optin gives same error((( – Илья Шулика Oct 12 '16 at 18:17
  • I think removing the "-" will be enough. – Martin Kleiven Oct 12 '16 at 18:42
  • But how fseek() would know that i need to move "left" from the "cursor"? – Илья Шулика Oct 12 '16 at 18:45
  • See my updated answer. I'm fairly certain it will work, but am not sure. – Martin Kleiven Oct 12 '16 at 19:04
  • 1
    try declaring width as long not int, I had the exact same error. But what i did was declared long offset = bi.biWidth*sizeof(RGBTRIPLE); and then used it in fseek( inptr, -offset, SEEK_CUR); – Jitesh Yadav Oct 12 '16 at 19:57

You must log in to answer this question.

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