0

Okay. I need help guys and girls. I feel like this is a problem that I should have solved by now and yet I just cant pin down the problem.

Originally I thought is was a problem with header calculation and since I made a few modifications I feel like I /may/ have dealt with it and I think they're calculating correctly.

Honestly I'm just stumped and I've been looking at this for hours so I think it might be time to just ask. What am I missing? I know that the custom is to hint at the issue, but just knowing where to start would be great.

EDIT: Output of running the peek tool:

offset  type   name              argv[1]   argv[2]
0       WORD   bfType               4d42      4d42
2       DWORD  bfSize           000001e6  000001e6
6       WORD   bfReserved1          0000      0000
8       WORD   bfReserved2          0000      0000
10      DWORD  bfOffBits        00000036  00000036
14      DWORD  biSize           00000028  00000028
18      LONG   biWidth          0000000c  0000000c
22      LONG   biHeight         fffffff4  fffffff4
26      WORD   biPlanes             0001      0001
28      WORD   biBitCount           0018      0018
30      DWORD  biCompression    00000000  00000000
34      DWORD  biSizeImage      000001b0  000001b0
38      LONG   biXPelsPerMeter  00000b12  00000b12
42      LONG   biYPelsPerMeter  00000b12  00000b12
46      DWORD  biClrUsed        00000000  00000000
50      DWORD  biClrImportant   00000000  00000000

EDIT: I've actually diff'ed the resulting files from this and from the staff version and I'm getting a result of the files being identical. I'm extra stumped now.

Here is what I have:

/**
 * resize.c
 *
 * Computer Science 50
 * Problem Set 4
 *
 * resizes an image (BMP).
 */

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

#include "bmp.h"

void writeScanline(RGBTRIPLE scanline[], FILE* outptr, BITMAPINFOHEADER bi)
{
   for(int i = 0; i < bi.biWidth; i++)
   {
     fwrite(&scanline[i], sizeof(RGBTRIPLE), 1, outptr); 
   }
}



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

    // remember filenames
    int factor = atoi(argv[1]);
    char* infile = argv[2];
    char* outfile = argv[3];

    if(factor > 100 || factor < 1)
    {
      printf("ERROR: positive int between 1 and 100 only");
      return 1;
    }

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


    int oldH = bi.biHeight; // These were previously long's
    int oldW = bi.biWidth;

    // determine padding for scanlines
    int oldpadding =  (4 - (oldW * sizeof(RGBTRIPLE)) % 4) % 4;

    bi.biHeight *= factor;
    bi.biWidth *= factor;

    int newpadding =  (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;


    bi.biSizeImage = abs(bi.biHeight) * ((bi.biWidth) + newpadding) * sizeof(RGBTRIPLE);
    bf.bfSize = bi.biSizeImage + bf.bfOffBits;


    RGBTRIPLE scanline[bi.biWidth];

    // 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, biHeight = abs(oldH); i < biHeight; i++)
    {
      int f = 0;
        // iterate over pixels in scanline
        for (int j = 0; j < oldW; j++)
        {
          // temporary storage
          RGBTRIPLE triple;

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

          // write RGB triple to outfile
          for(int x = 0; x < factor; x++)
          {
            scanline[f] = triple;

            if(f == bi.biWidth - 1)
            {
              for(int y = 0; y < factor; y++)
              { 
                writeScanline(scanline, outptr, bi);
              }

              f = 0;
            }
            else
              f++;
          }
        }

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

        // then add it back (to demonstrate how)
        for (int k = 0; k < newpadding; k++)
        {
            fputc(0x00, outptr);
        }
    }
    printf("%i\n", bf.bfSize); // This gets commented out when I'm checking it against check50

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

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

OK, for the header, take a look at the following line:

bi.biSizeImage = abs(bi.biHeight) * ((bi.biWidth) + newpadding) * sizeof(RGBTRIPLE);

To point you in the right direction, why do you multiply by sizeof(RGBTRIPLE)? Is biWidth made of RGBTRIPLES? What about newpadding? Is it made of triples too?

Moving on to the image code. While it works for factor==1, it fails for 2 or more. If you look very carefully at the image data of the output file using the xxd tool, you would see that, when processing a line from the input file, it will output the scaled up line of pixels factor times and then will add the padding. Unfortunately, you need to add the padding after each line of output, not after all the output lines have been written for each input line.

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

1
  • I found exactly what I was doing wrong and figured it all out. Thanks! – David Cramer Dec 20 '16 at 18:12

You must log in to answer this question.

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