0

I'm having problems with my vertical re-size in Pset4. I've got the horizontal re-size working - go me! But I'm having problems with the vertical re-size. I'm trying to implement a version of what Zamyla calls the "re-copy" method. I've pasted my code below, from the point after where I've written the header files to the output file successfully):

// Now iterate over infile's scanlines
    for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++) //     iterates the number of times equal to the field "bi.biHeight" (i.e. the no. of
                                                                    // pixels the original image is "high" = the number of lines in the image)
    {
        for (int ctr = 0; ctr < (n-1); ctr++) // does the following n-1 times
        {
            // **************************************************************************************************************
            // execute horizontal re-sizing, including adding padding required to each line in the outfile - "horiz (n);"
            {
                // iterate over pixels in scanline
                for (int j = 0; j < bi.biWidth; j++) // Iterates the number of times the original image is wide
                {
                    // temporary storage
                    RGBTRIPLE triple; // Creates a struct of format RGBTRIPLE in a temporary buffer called "triple"

                    // read RGB triple from infile
                    fread(&triple, sizeof(RGBTRIPLE), 1, inptr); // Reads something the size of an RGBTRIPLE (3 bytes) from the infile *once*
                                                                 // and stores it in the temporary RGBTRIPLE called "triple"

                    // write RGB triple to outfile, resizing as we go
                    for (int k = 0; k < n; k++) // Iterates n times (where n is the factor entered by the user - see line 30)
                    {
                        fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr); // Writes the 3 bytes stored in "triple" to the outfile
                    }
                }

                // Add padding to outfile as needed
                for (int l = 0; l < output_padding; l++) // Iterates over the number of units of padding required in the output...
                {
                   fputc(0x00, outptr); // ...and writes "0x00" to the outfile at the end of each scanline
                }
            }
            // **************************************************************************************************

            // skip back to beginning of input line
            fseek(inptr, -((bi.biWidth * sizeof(RGBTRIPLE))-1), SEEK_CUR); // In the file pointed to by inptr (i.e the infile), starting from the current "cursor position", 
                                                                           // move *backward* by bi.biWidth (i.e. the number of pixels in each row in the infile, before padding) * the size of each RGBTRIPLE
        }    

        // repeat the horizontal write code ["horiz()" function]
        {
            // iterate over pixels in scanline
            for (int m = 0; m < bi.biWidth; m++) // Iterates the number of times the original image is wide
            {
                // temporary storage
                RGBTRIPLE triple; // Creates a struct of format RGBTRIPLE in a temporary buffer called "triple"

                // read RGB triple from infile
                fread(&triple, sizeof(RGBTRIPLE), 1, inptr); // Reads something the size of an RGBTRIPLE (3 bytes) from the infile *once*
                                                             // and stores it in the temporary RGBTRIPLE called "triple"

                // write RGB triple to outfile, resizing as we go
                for (int o = 0; o < n; o++) // Iterates n times (where n is the factor entered by the user - see line 30)
                {
                    fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr); // Writes the 3 bytes stored in "triple" to the outfile
                }
            }

            // Add padding to outfile as needed
            for (int p = 0; p < output_padding; p++) // Iterates over the number of units of padding required in the output...
            {
               fputc(0x00, outptr); // ...and writes "0x00" to the outfile at the end of each scanline
            }
        }

        // skip over padding in infile, if any
        fseek(inptr, input_padding, SEEK_CUR); // In the file pointed to by inptr (i.e the infile), starting from the current "cursor position", 
                                               // move forward by "input padding" (which is 3 bytes for "small.bmp")
    }

The code compiles, but when I run it with a factor of 3, I get the following error: " resize.c:147:26: runtime error: negation of 8 cannot be represented in type 'unsigned long' " Line 147 is the line where I skip back to the beginning of the infile line. I understand why an unsigned long can't take a value of (-8). What I don't understand is - why does fseek require an unsigned long? Can I change this, somehow? And if not, how do I go backwards?

NB - the code inside the two //***** lines is my horizontal re-size code. I wrote it like this because I thought I might be able to extract it as a function and just call that here (where it's repeated (n-1) times), and then below - which would be more elegant and functionally disaggregated. As an aside, that's tricky as it refers to other variables that have been defined in main() (such as the biwidth etc.) - so these are local to main and not available to a separate function. Any thoughts on that would be appreciated, too!

Many thanks in advance for your help. Matt

1

fseek does not require an unsigned long, the signature is
int fseek(FILE *stream, long offset, int whence);

The runtime error stems from this calculation -((bi.biWidth * sizeof(RGBTRIPLE))-1). sizeof returns a size_t type which is unisigned. The result of the calculation will be unsigned according to promotion rules in the "New C Standard 6.3.8.1". It is complaining about the minus sign.

You could do the calculation in a new (signed) variable, eg long offset = bi.biWidth * sizeof(RGBTRIPLE);, then fseek(inptr,-offset,SEEK_CUR);.

Which calls to question why subtract 1? Isn't -bi.biWidth * sizeof(RGBTRIPLE) the beginning of the scanline (as described in the comment)?

As for making a function, another option might be to do the ctr loop n times, and conditionally skip backwards or forwards, depending on ctrs relation to n. That would avoid duplicating code.

| improve this answer | |
  • Thanks DinoCoderSaurus! Creating the signed variable solved it. Re. subtracting 1, I had a little "brain fart" about how far back I needed to go. Originally I had it set at the length of the scanline. Then I started thinking "I'm at position 9, I need to get back to position 1, so I need to step back 8 times" (or 8 and 0). But of course the "cursor" is at the end of the 9th position, and needs to get back to just before the 1st position - so it needs to go back 9 times i.e. the length of the scanline (before padding). Thanks also for the idea to make the ctr loop conditional-I'll have a play. – Matt Friend Feb 19 '17 at 22:12

You must log in to answer this question.

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