1

I am trying to solve pset4/resize.c using the recopy method (i.e. allocating memory and using a buffer to write the line to it and then repeat it).

However the final picture only shows black with a vertical red line in it. I have been trying to figure it out, but cannot find the mistake.

I was wondering if the padding is the issue (because of the black colour), but commenting it out did not change anything. For those who wonder: using 1 as scaling factor also produces a black picture.

I have been spending hours on trying to determine the mistake, maybe a fresh pair of eyes can help. Here is the code:

int main(int argc, char* argv[])
{
    // ensure proper usage
    if (argc != 4)
    {
        printf("Usage: ./copy 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;
     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 outfile bitmapfileheader
     BITMAPFILEHEADER bfout;
     bfout = bf;



     // create outfile bitmapinfoheader
     BITMAPINFOHEADER biout;
     biout = bi;
     biout.biWidth = bi.biWidth *n;
     biout.biHeight = bi.biHeight *n;


     // determine padding for scanlines
     int padding =  (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
     int paddingout = (4- (biout.biWidth *sizeof(RGBTRIPLE)) % 4) % 4;

     //calculate bfSize
     biout.biSizeImage = (biout.biWidth * sizeof(RGBTRIPLE) + paddingout) * abs(biout.biHeight);
     bfout.bfSize = biout.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

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

     //write outfile bitmapinfoheader
     fwrite(&biout, sizeof(BITMAPINFOHEADER), 1, outptr);


     //allocate memory for storing scanline
     RGBTRIPLE* buffer = malloc(bi.biWidth*sizeof(RGBTRIPLE));


     // iterate over infile's scanlines
     for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
     {

          // 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, inptr);

               // write RGB triple to buffer while resizing horizontally to n-times the size
               int l; //counter for repeatedly writing pixels
               int t=0; //tracker variable for the buffer

               for(l=0; l<n; l++)
               {
                    *(buffer + t) = triple;
                    t++;
               }   

          }

         // skip over padding, if any
         fseek(inptr, padding, SEEK_CUR);

         //write the buffer n times
         for(int t = 0; t < n; t++)
         {
              fwrite(buffer, sizeof(RGBTRIPLE), biout.biWidth, outptr);  


              for (int k = 0; k < paddingout; k++)
              {
                   fputc(0x00, outptr);
              }
    }



}

//free buffer
free(buffer);

// close infile
fclose(inptr);

// close outfile
fclose(outptr);

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

Your code is fixable with 3 adjustments.

  1. The biggest problem is that your "tracker variable" (t) for your buffer gets reset to 0 for every pixel of the infile, rather than for every line. In other words, each scaled pixel is recopied into the first n spots of buffer. Fix this by moving int t = 0 outside by one for loop.
  2. Change the variable t that appears in a later for loop, because there are now two conflicting variables t.
  3. The memory allocated to the buffer variable must be changed. It should be biout.biWidth*sizeof(RGBTRIPLE) rather than bi.biWidth*sizeof(RGBTRIPLE).

    int main(int argc, char* argv[])
    {
    // ensure proper usage
    if (argc != 4)
    {
        printf("Usage: ./copy 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;
     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 outfile bitmapfileheader
     BITMAPFILEHEADER bfout;
     bfout = bf;
    
    
    
     // create outfile bitmapinfoheader
     BITMAPINFOHEADER biout;
     biout = bi;
     biout.biWidth = bi.biWidth *n;
     biout.biHeight = bi.biHeight *n;
    
    
     // determine padding for scanlines
     int padding =  (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
     int paddingout = (4- (biout.biWidth *sizeof(RGBTRIPLE)) % 4) % 4;
    
     //calculate bfSize
     biout.biSizeImage = (biout.biWidth * sizeof(RGBTRIPLE) + paddingout) * abs(biout.biHeight);
     bfout.bfSize = biout.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
    
     //write outfile bitmapfileheader
     fwrite(&bfout, sizeof(BITMAPFILEHEADER), 1, outptr);
    
     //write outfile bitmapinfoheader
     fwrite(&biout, sizeof(BITMAPINFOHEADER), 1, outptr);
    
    
     //allocate memory for storing scanline
     RGBTRIPLE* buffer = malloc(biout.biWidth*sizeof(RGBTRIPLE));
    
    
     // iterate over infile's scanlines
     for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
     {
    
          int t=0; //tracker variable for the buffer
          // 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, inptr);
    
               // write RGB triple to buffer while resizing horizontally to n-times the size
               int l; //counter for repeatedly writing pixels
    
               for(l=0; l<n; l++)
               {
                    *(buffer + t) = triple;
                    t++;
               }   
    
          }
    
         // skip over padding, if any
         fseek(inptr, padding, SEEK_CUR);
    
         //write the buffer n times
         for(int x = 0; x < n; x++)
         {
              fwrite(buffer, sizeof(RGBTRIPLE), biout.biWidth, outptr);  
    
    
              for (int k = 0; k < paddingout; k++)
              {
                   fputc(0x00, outptr);
              }
    }
    
    
    
    }
    
    //free buffer
    free(buffer);
    
    // close infile
    fclose(inptr);
    
    // close outfile
    fclose(outptr);
    
    // that's all folks
    return 0;
    }
    
2
  • Awesome, thank you so much! Sometimes it's these little things that a fresh set of eyes spots immediately. I had - in the meantime - realized I needed to allocate with biout.biWidth; however taking t out of the for loop evaded me. – mor3dr3ad Aug 4 '16 at 9:06
  • No problem! Glad I could help :) – Omid Aug 5 '16 at 20:30

You must log in to answer this question.

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