0

I know that this question has been "answered" numerous times but those revelations haven't related to me for some reason. My code is edited from copy.c and a few other resources. The FILE reads and writes before INFO headers in both instances. I ran debug50 on my code and then someone elses that I copied into a different file but same results happen each time. I tried it with a third and same thing. The only thing I saw that was weird was that it skipped completely over the scanLine for loop and I think it's because bi.biHeight is -3 throughout the whole process. I don't know if that's supposed to be a negative or if it even matters but nothing is happening within that for loop I'm sure. I did the math manually and it makes sense. the xxd terminal output is fudged. Please, please, please, help even though this has been answered. I'm not finding success through those answers.

/**
 * Resizes a BMP piece by piece
 */

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

#include "bmp.h"

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

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

    int multiplier = atoi(argv[1]);
    printf("multiplier: %d\n", multiplier);

    //end program if multiplier is negative or too large
    if(multiplier < 1 || multiplier > 100)
    {
        printf("Invalid zoom factor of %i\n Zoom factor must be 1-100\n", multiplier);
        return 5;
    }

    // open input file 
    FILE *small = fopen(infile, "r");

    if (small == NULL)
    {
        fprintf(stderr, "Could not open %s.\n", "small");
        return 2;
    }

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

    // read infile's BITMAPFILEHEADER
    BITMAPFILEHEADER bf;
    fread(&bf, sizeof(BITMAPFILEHEADER), 1, small);

    // read infile's BITMAPINFOHEADER
    BITMAPINFOHEADER bi;
    fread(&bi, sizeof(BITMAPINFOHEADER), 1, small);

    // 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(zoom);
        fclose(small);
        fprintf(stderr, "Unsupported file format.\n");
        return 4;
    }

        BITMAPFILEHEADER bfOut;
        BITMAPINFOHEADER biOut; 
        bfOut = bf;
        biOut = bi;
        biOut.biWidth = bi.biWidth * multiplier;
        biOut.biHeight = bi.biHeight * multiplier;

        int paddingIn =  (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
        int paddingOut =  (4 - (biOut.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

        bfOut.bfSize = 54 + biOut.biWidth * abs(biOut.biHeight) * 3 + abs(biOut.biHeight) *  paddingOut;
        biOut.biSizeImage = ((((biOut.biWidth * biOut.biBitCount) + 31) & ~31) / 8) * abs(biOut.biHeight);


    // //multiply image size
    // biOut.biWidth = bi.biWidth * multiplier;
    // biOut.biHeight = bi.biHeight * multiplier;
    // printf("biWidth:  %d\n", biOut.biWidth);
    // printf("biHeight: %d\n", biOut.biHeight);

    // //determine padding for scanlines
    // int paddingIn = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
    // int paddingOut = (4 - (biOut.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
    // printf("paddingIn: %d | width: %d\n", paddingIn, bi.biWidth);
    // printf("paddingOut: %d\n", paddingOut);

    // determine file size
    // biOut.biSizeImage = ((biOut.biWidth * sizeof(RGBTRIPLE)) + paddingOut) * biOut.biHeight;
    // bfOut.bfSize = bf.bfSize - bi.biSizeImage + biOut.biSizeImage;

    // write outfile's BITMAPFILEHEADER
    fwrite(&bfOut, sizeof(BITMAPFILEHEADER), 1, zoom);

    // write outfile's BITMAPINFOHEADER
    fwrite(&biOut, sizeof(BITMAPINFOHEADER), 1, zoom);

    // iterate over height of file
    for (int i = 0; i < (bi.biHeight = abs(bi.biHeight)); i++)
    {
        // iterate over infile's scanlines
        for (int scanLine = 0; scanLine < multiplier; scanLine++) 
        {
            // 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, small);

                // write RGB triple to outfile
                for (int w = 0; w < multiplier; w++)
                {
                    fwrite(&triple, sizeof(RGBTRIPLE), 1, zoom);
                }
            }
            // skip over padding, if any
            fseek(small, paddingIn, SEEK_CUR);

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

                fseek(small, -(bi.biWidth * 3 + paddingIn), SEEK_CUR);
        }

        fseek(small, bi.biWidth * 3 + paddingIn, SEEK_CUR);




        // if(i % multiplier != 0)
        // {
        //     fseek(small, (-biOut.biWidth * /*sizeof(RGBTRIPLE)*/3) + paddingIn, SEEK_CUR);
        // }
    }

    // close infile
    fclose(small);

    // close outfile
    fclose(zoom);

    // success
    return 0;
}
1

There is a single significant issue that is affecting the code in several places. It appears that you were starting to comprehend it, so let's fill in the blank.

Yes, the sign of biHeight is significant. It determines whether the image is painted on the screen from the top down or from the bottom up as the data is sequentially read. The sign of biHeight must be preserved when the image file is processed.

However, the absolute value of biHeight is used for several functions in this pset and must be positive for these purposes, no matter whether the sign of biHeight is positive or negative. You need to deal with this in your code.

The code will need a few mods to function correctly. Once completed, there are other issues that also need to be identified and corrected, but who am I to deprive you of that opportunity? ;-)

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

11
  • Thank you cliff. I suspected you'd be answering at some point. I did try to use abs(bi.biHeight) for the for loop but that caused a way bigger problem it seemed. I've been over this code for hours and hours the passed 2 days and can't see where it is you are subtly pointing me to start. What REALLY kills me is that the two completed programs I found on GitHub I believe, do not work either and give the same exact error. I'll keep at it and maybe I'll see something a tad off. – Michael Haley Sep 4 '17 at 22:21
  • You just learned an important lesson. ;-) Sometimes, when you fix a small problem, it reveals a much larger problem that was masked. While it may seem like fixing the small problem is causing the larger problem, the reality is that both must be fixed. It may seem like things got worse, but the opposite is true. The trick is recognizing the difference between causing a bigger problem and unmasking a bigger problem! It comes with experience. ;-) – Cliff B Sep 4 '17 at 22:27
  • In case you haven't figured it out, try this. First, work with a resize factor of 1 with small.bmp. Get the header right. Only then, work on getting the image right. Once resize of 1 works perfectly, repeat the process with 2. Get the header right, and only then, work on the image. And remember, peek and xxd are your friends! – Cliff B Sep 4 '17 at 22:30
  • Okay, so, I've repaired a bunch of that stuff with biHeight and biWidth. I think I got a bunch of them mixed up. Didn't really understand the values enough. I get this error now when I run a multiplier of 2: resize.c:124:36: runtime error: unsigned integer overflow: 18446744073709551613 * 3 cannot be represented in type 'unsigned long' A multiplier of 1 works fine. All is well. 2 or more, it feeds this error. Where does it get the 3 from and why is that number so big?!?! – Michael Haley Sep 5 '17 at 5:57
  • Can't really answer that without seeing the actual code. Can you update the question with your current version? BTW, please review the following to see how to format code for stack exchange: meta.stackexchange.com/questions/22186/… – Cliff B Sep 5 '17 at 6:04
0

I found several finished products online and cross-referenced them to mine and found 2 significant reasons why my code was off. First, and most apparent was the fseek usage. I honestly don't see how the computation is incorrect while using the sizeof(RGBTRIPLE) but replacing that with 3 worked in this case. Second, the equation I was using to change the file size was way off. I found a crazy one and popped that in and voila! The little "black box" works with my code.  

I left the broken parts there and commented them out. I edited how I declared the biOut and bfOut. AND I changed the for loops to include fseek BEFORE the exit of the scanLine loop...phew

You must log in to answer this question.

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