1

I am having a problem with my code, and I think it has to do with the use of fseek. I have read a lot of the articles on the cs50 Stack Exchange, and tweaked my code a lot, but my problem still remains, and I don't understand how to fix it. Here is 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\n");
           return 1;
       }

       // remember filenames
       int n = atoi(argv[1]);
       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, bfout;
       fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr);
       bfout = bf;

       // read infile's BITMAPINFOHEADER
       BITMAPINFOHEADER bin, bout;
       fread(&bin, sizeof(BITMAPINFOHEADER), 1, inptr);
       bout = bin;

       // ensure infile is (likely) a 24-bit uncompressed BMP 4.0
       if (bf.bfType != 0x4d42 || bf.bfOffBits != 54 || bin.biSize != 40 || 
           bin.biBitCount != 24 || bin.biCompression != 0)
       {
           fclose(outptr);
           fclose(inptr);
           fprintf(stderr, "Unsupported file format.\n");
           return 4;
       }
    // update outfile's BITMAPINFOHEADER width and height
       bout.biHeight = bin.biHeight * n;
       bout.biWidth = bin.biWidth * n;

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

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

       // determine padding for scanlines
       int in_padding = (4 - (bin.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
    int out_padding = (4 - (bout.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
       // iterate over infile's scanlines
       for (int i = 0, biHeight = abs(bout.biHeight); i < biHeight; i++)
       {
                for(int m = 0; m < n; m++)
                {
                    if(m != 0)
                    {
                        fseek(inptr, in_padding, SEEK_CUR);
                    }
                // iterate over pixels in scanline
                    for (int j = 0; j < bin.biWidth; j++)
                    {
                        // temporary storage
                        RGBTRIPLE triple;

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

                        // write RGB triple(s) to outfile
                        for(int k = 0; k < n; k++)
                        {
                            fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
                        }
                    }
                }
                // adds new padding
                for (int p = 0; p < out_padding; p++)
                {
                    fputc(0x00, outptr);
                }
       }

       // close infile
       fclose(inptr);

       // close outfile
       fclose(outptr);

       // that's all folks
       return 0;
   }
1

One of the problems is that you're not resizing vertically. What you're doing is: 1) read one triple and write it as many times as needed by resize factor. Repeat this until a whole scanline has been read and written. (All this is correct)

2)Then you skip the infile's padding.

3) You repeat steps 1 and 2 n amount of times. But each time you start the process, you're reading a new scanline: You're not reading the same scanline n times.

4) When you're done reading and writing n scanlines, you write the new padding.

5) You repeat the full process as many times as the updated height. (This is also incorrect)

So, suppose your file is 3 x 3 and you're resizing by 2. So it should be 6 x 6. In total, you're writing 12 scanlines (instead of 6). But also, after you wrote the first 3, you're actually writing garbage that's found after the EOF.

The idea would be 1) Write the innermost loop the same way as you do. At the end, you've written a full scanline 2) Add the corresponding padding to the outfile's scanline 3) Write this same scanline n times. 4) Repeat points 1-3 as much as height (original height, because you're already multiplying by n by writing n scanlines :) )

The padding of the file you're reading from, you'll have to skip at some point, depending on how you go about step 3, it will change.

0

I advice you to first calculate the padding size of the old file, then, somewhere in the loop, use fseek() to skip over it. I recently finished it, and the vital statement was actually a fseek. The rest of your code is fine.✔ without the padding, when you scale the image, you will get something like this: ./resize 2 small.bmp temp.bmp (with a scale factor of 2).

If you can't see it well,

x10

(Scaled it by 10 times)

You must log in to answer this question.

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