0

I'd been starting at this for hours and can't figure out what I'm doing wrong. To scale for the horizontal I put fwrite() in a for loop repeating n times for each pixel. To scale vertically I put the whole code in another for loop in where it goes back to the start of the old scanline, re-reading and re-rewriting it.

Here's my code:

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

#include "bmp.h"

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

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

    int n = atoi(argv[1]);

    if (n <= 0 && n>= ((2^32)-1))
    {
        printf("n should be less than 2^32-1");
        return 2;
    }

    // open input file 
    FILE* inptr = fopen(infile, "r");
    if (inptr == NULL)
    {
        printf("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 4;
    }

    //old
    int oldWidth = bi.biWidth;
    int oldHeight = abs(bi.biHeight);
    int oldPadding =  (4 - (oldWidth * sizeof(RGBTRIPLE)) % 4) % 4;  //padding = 3

    //new
    bi.biWidth *= n;
    bi.biHeight *= n;

    int padding =  (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;  //padding = 3
    bi.biSizeImage = ((sizeof(RGBTRIPLE) * bi.biWidth) + padding) *abs(bi.biHeight);
    bf.bfSize = bi.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

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

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

    // iterate over infile's scanlines
    for (int i = 0;  i < oldHeight; i++)  //oldHeight = 3
    {  
        for(int a=0; a<n;a++)               //resizing vertically
        {
            // iterate over pixels in scanline
            for (int j = 0; j < oldWidth; j++)  //bi.biWidth = 6
            {
                // temporary storage
                RGBTRIPLE triple;

                // read RGB triple from infile
                fread(&triple, sizeof(RGBTRIPLE), 1, inptr);

                // write RGB triple to outfile (repeated n times for each pixel)
                for(int r=0; r< n ; r++)
                    fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);

             }

                // skip over padding, if any
             fseek(inptr, oldPadding, SEEK_CUR);  //skipping padding of infile (3)


          // then add it back (to demonstrate how)
            for (int k = 0; k < padding; k++)    //new padding = 2
            {
                fputc(0x00, outptr);
            }
        fseek(inptr, -(oldWidth+oldPadding), SEEK_CUR);  //going back 

        }


    }
    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // that's all folks
    return 0;
}

Output:

~/workspace/pset4/bmp/ $ ./resize 2 small.bmp t.bmp

enter image description here

Any help would be appreciated.

1 Answer 1

2

I see three issues with your code. The good news is that you're pretty much on target.

Two of the problems are related to the backwards fseek near the end of the for loops. The fseek backwards executes after every execution. This shouldn't be done after n lines have been written to the output file. As written, it goes back one time too many for each line in the input file. I'll leave it to you to figure out how to implement the change. ;-)

Next, the fseek isn't going back the correct amount. Here's the big hint. What units are used to measure oldWidth and what units are oldpadding? Bytes or pixels?

Finally, a problem that wouldn't be caught by check50. The program spec says that the scale factor goes from 1 to 100, not 2^32. Further, the ^ operator may mean exponent in traditional math, but in programming, it is a bit shift operator, something totally different.

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

6
  • wouldn't the infile pointer when it has arrived at the end of the a loop be at the end of the scanline, after it skipped the padding? I thought that's what it was doing, so I just put it back to the start of the scanline and re-read it again so I can print it again...
    – tadm123
    Commented Dec 19, 2016 at 4:26
  • What you said is true. The problem is this. Say that n is 3. You need to process the input line 3 times. That means that you need to go back 3 times, not 3. If you go back 3 times, it will be cued up at the beginning of the first line when you want to start processing the second line.
    – Cliff B
    Commented Dec 19, 2016 at 4:30
  • Also, the amount/distance that you're moving isn't correct. Close, but not correct. ;-)
    – Cliff B
    Commented Dec 19, 2016 at 4:31
  • Thanks for pointing that out, I corrected fseek(), converting pixes to bytes: fseek(inptr, -(oldWidth*3)-oldPadding, SEEK_CUR)
    – tadm123
    Commented Dec 19, 2016 at 4:35
  • I also put the condition: if(a != n-1) in the fseek() function and it works now. Thanks a lot!
    – tadm123
    Commented Dec 19, 2016 at 4:44

You must log in to answer this question.

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