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