0

I have been working on resize.c(less comfortable) for days (tears hair out). My code is able to resize just fine but the colours of the output image are messed up. I just can't seem to find any logical fault in my code, despite having trawled through CS50 reddit and stackexchange.

Moreover, peek shows that my output matches the staff's implementation. My only guess is that the problem lies with the padding and seek but I am not sure where since the code I have written for them seem logical to me too.

This is how I understand the logic dealing with the infile padding after each row is copied and resized accordingly:

Since the cursor has moved bi.biWidth number of pixels to the right in the infile, one way to resize it vertically is by calling the fseek function to move the cursor back bi.biWidth number of pixels in infile. Hence, there is no need to skip the padding in the original picture until the last vertical resize. At the last vertical resize, using fseek, cursor should skip over infile padding, if any, so that the cursor can move and start iterating infile’s scanlines from the second row of infile, in this case, small.bmp.

Any help and explanation of the reasoning behind would be immensely appreciated!!

Here is my code and the relevant images below:

#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;
    }

   // validate user input: check resize n
   int n = atoi(argv[1]);

   if (n < 0 || n > 100)
   {
       printf("Resize n should be a positive integer less than 100.\n");
       return 2;
   }


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

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

   // open output file for writing
   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;
   }

   // create copy of original dimensions
   int biWidth_original = bi.biWidth;
   int biHeight_original = bi.biHeight;

   // update image dimensions in BITMAPFILEHEADER in bmp.h file
   bi.biWidth *= n;
   bi.biHeight *= n;

   // determine padding for scanlines (padding is measured in pixels)
   int padding_original = (4 - (biWidth_original * sizeof(RGBTRIPLE)) % 4) % 4;
   int padding_resize = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

   // update image size
   bi.biSizeImage = abs(bi.biHeight) * ((abs(bi.biWidth) * 
                 sizeof(RGBTRIPLE)) + padding_resize);

   // update file size
   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 height of image
   for (int i = 0; i < biHeight_original; i++)
   {
       // scale vertically: write each row to outfile n times
       for (int j = 0; j < n; j++)
       {
           // iterate through pixels in scan line (one loop for one pixel)
           for (int k = 0; k < biWidth_original; k++)
           {
               // temporary storage
               RGBTRIPLE triple;

               // read RGB triple from infile, one at a time!
               fread(&triple, sizeof(RGBTRIPLE), 1, inptr);

               // scale horizontally: write each pixel to outfile n times
               for (int l = 0; l < n; l++)
               {
                   // write RGB triple to outfile
                   fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
               }
           }

           // add padding back to outfile
           for (int m = 0; m < padding_resize; m++)
           {
               fputc(0x00, outptr);
           }

           if (j < n - 1)
           {
               // reset cursor to start of scanline
               fseek(inptr, -(biWidth_original * sizeof(RGBTRIPLE)),
                  SEEK_CUR);
           }
           else
           {
               // If at last vertical line, skip infile padding in order for cursor to move on to next row 
               fseek(inptr, padding_original, SEEK_CUR);
           }
       }
   }

   // close infile
   fclose(inptr);

   // close outfile
   fclose(outptr);

   // success
   return 0;
}

My code's output matching staff's When small.bmp is resized by factor of 1 When small.bmp is resized by factor of 2 When small.bmp is resized by factor of 3 When small.bmp is resized by factor of 4

1
  • Considering the images and the fact that peek doesn't measure padding, I'd say your problem probably lies in padding...
    – Jason_V
    Commented Jun 28, 2017 at 2:55

1 Answer 1

1

Please note that biHeight_original = bi.biHeight are both negative. So you do not do a single iteration, as i < biHeight_original is false.

3
  • Ahhh so it was all because of not having added abs before bi.biHeight and bi.biWidth..........to account for the fact that height of a bmp image can be negative- if the image is stored top to bottom which has to be corrected when figuring out the size of the image. I made the necessary changes and my code just passed Check50! F i n a l l y. Thank you so much! Commented Jun 28, 2017 at 3:48
  • May I know how this error results in the resized image sporting only grey or white colours? Commented Jun 28, 2017 at 3:53
  • Not quite sure. I suppose that is the way .bmp viewer treats empty file, with just Headers
    – obesman
    Commented Jun 28, 2017 at 3:55

You must log in to answer this question.

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