0

ive been working on "resize less" for a week now and i've been able to successfully resize images. In addition, the staff header is exactly the same as mine. However when i run check50 i fail all the test, because it states that the image has more bytes than expected. As result i've been reading through as many question on here and reddit but failed to find a solution to my code. So if someone could help me out it would be much appreciated.

*Side note: I used a float to store the key since I initially started resize (more comfortable) before deciding i should probably start with the less comfortable since I was having problems.

Here's my code:

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

    // change key number from an int to a float
    float key = atof(argv[1]);
    if(key == 0)
    {
        fprintf(stderr, "f must be in the range of 0 < f <= 100\n");
        return 1;
    }

    // remember filenames
    char *infile = argv[2];
    char *outfile = argv[3];

    // open input file
    FILE *inptr = fopen(infile, "r");
    if (inptr == NULL)
    {
        fprintf(stderr, "Could not open %s.\n", infile);
        return 3;
    }

    // open output file
    FILE *outptr = fopen(outfile, "w");
    if (outptr == NULL)
    {
        fclose(inptr);
        fprintf(stderr, "Could not create %s.\n", outfile);
        return 4;
    }

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

    int orig_padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
    // Copy old header to new header to ensure all but the 4 element that are affected by image resizing stay the same
    BITMAPFILEHEADER bfnew;
    BITMAPINFOHEADER binew;
    binew = bi;
    bfnew = bf;

   // Change the height, width, image size and file size of the new output file
    binew.biWidth = bi.biWidth * key;
    binew.biHeight = bi.biHeight * key;

    int new_padding = (4 - (binew.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

    binew.biSizeImage = ((sizeof(RGBTRIPLE)*binew.biWidth) + new_padding) * abs(binew.biHeight);
    bfnew.bfSize = binew.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

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

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

    // Count how many times scanline has been read
    int count_scan = 0;
    // iterate over infile's scanlines
    for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
    {
        //Resize vertically
        for(int count_hor = 0; count_hor <= key; count_hor++)
        {
            // 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);
                // resize horizontally
                for(int ic = 0; ic < key; ic++)
                {
                    // write RGB triple to outfile
                    fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
                }
            }

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

            // Add padding to the output file if necessary
            for (int k = 0; k < new_padding; k++)
            {
                fputc(0x00, outptr);
            }
            // If scanline line has been read the same number of times as the key then move on to the next if not keep reading and rewriting
            count_scan ++;

            if(count_scan < key)
            {
                fseek(inptr, -1 * ((bi.biWidth * sizeof(RGBTRIPLE)) + orig_padding), SEEK_CUR);
            }else{
                    count_scan = 0;
            }

        }
    }

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // success
    return 0;
}
1

I'll give you a big hint. The code is producing 3 extra lines of pixels in each output file, using a resize factor of 1, 2, or 3.

Did you actually look at the raw data in the file, or just at the image? When the image is displayed, it looks correct because the actual image part of the file is correct. The header data controls what is displayed from the image file, so any extra data at the end is not displayed. You wouldn't notice any extra data unless you check file sizes or actually used a tool like xxd to look at the raw date.

It looks like you have some flaws in your for loop logic. It's good that the image is being correctly scaled horizontally and vertically, but you need to figure out why it is adding extra data at the end of the file.

1
  • You're right i was only looking at the image, when comparing file sizes mine is definitely bigger than the staff's solution. I checked my for loops and corrected the issue and it works perfectly now, thank you.
    – Mamba808
    Dec 16 '19 at 17:47

You must log in to answer this question.

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