Hi, everyone!
I am currently finishing (after quite some thought and a lot of trial-and-error) the less comfortable version of the resize problem from pset4, which, as you probably know, resizes BMP images based on an integer command-line argument provided by the user.
While, as far as my tests have gone, the output files are graphically consistent with the stipulated resizing factors, on some scenarios the output file size does not match the expected bfSize
.
check50
exposes this problem when using n = 2
and n = 3
on small.bmp
.
I have looked through some questions; however, since I did not find so far anything related with the specific problem which I am going through, I'd love some assistance from you, guys!
If it is not asking too much, can you also give me a head-start on the changes I would have to make on my code in order to pass the more comfortable version of this problem? I know, of course, that I'd have to change resizingFactor
from int
to float
; however, I think I'll have some trouble dealing with the decimal part of the number provided by the user.
Here follows my code:
// Copies a BMP file
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "bmp.h"
int main(int argc, char *argv[])
{
// ensure proper usage
if (argc != 4 || *argv[1] > 100 || argv[1] <= 0)
{
fprintf(stderr, "Usage: ./resize n infile outfile\n");
return 1;
}
// remember filenames
char *infile = argv[2];
char *outfile = argv[3];
// remember resizing factor
int resizingFactor = round(atoi(argv[1]));
printf("Resizing Factor: %i\n\n", resizingFactor);
// open input file
FILE *inptr = fopen(infile, "r");
if (inptr == NULL)
{
fprintf(stderr, "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;
}
// [DEBUG]
printf("Initial biWidth: %d\nInitial biHeight: %d\nInitial biSizeImage: %u\n\nInitial bfSize: %u\n\n", bi.biWidth, bi.biHeight,
bi.biSizeImage, bf.bfSize);
// changing headers in accordance with the stipulated resizing factor
LONG originalWidth = bi.biWidth, originalHeight = bi.biHeight;
bi.biWidth = bi.biWidth * resizingFactor;
bi.biHeight = bi.biHeight * resizingFactor;
if ((bi.biWidth % 4) == 0)
{
bi.biSizeImage = bi.biWidth * abs(bi.biHeight) * 3;
}
else
{
bi.biSizeImage = 3 * (bi.biWidth + (4 - (bi.biWidth % 4))) * abs(bi.biHeight);
}
bf.bfSize = sizeof(bf) + sizeof(bi) + bi.biSizeImage;
// [DEBUG]
printf("Final biWidth: %d\nFinal biHeight: %d\nFinal biSizeImage: %u\n\nFinal bfSize: %u\n\n", bi.biWidth, bi.biHeight,
bi.biSizeImage, bf.bfSize);
printf("Original Width: %d\nOriginal Height: %d\n\n", originalWidth, originalHeight);
// write outfile's BITMAPFILEHEADER
fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr);
// write outfile's BITMAPINFOHEADER
fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr);
// determine padding for scanlines
int originalPadding = (4 - (originalWidth * sizeof(RGBTRIPLE)) % 4) % 4;
int padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
printf("Original Padding: %d\nFinal Padding: %d\n\n", originalPadding, padding);
// iterate over infile's scanlines
for (int i = 0, biHeight = abs(originalHeight); i < biHeight; i++)
{
for (int j = 0; j < resizingFactor; j++)
{
// iterate over pixels in scanline
for (int k = 0; k < originalWidth; k++)
{
// temporary storage
RGBTRIPLE triple;
// read RGB triple from infile
fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
for (int l = 0; l < resizingFactor; l++)
{
// write RGB triple to outfile
fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
}
}
// add padding
for (int m = 0; m < padding; m++)
{
fputc(0x00, outptr);
}
// going back to replicate the same line
if (j < resizingFactor - 1)
{
fseek(inptr, -(originalWidth * (int)sizeof(RGBTRIPLE)), SEEK_CUR);
}
}
// skip over padding, if any
fseek(inptr, originalPadding, SEEK_CUR);
}
// close infile
fclose(inptr);
// close outfile
fclose(outptr);
// success
return 0;
}
Thank you in advance for the assistance provided. I hope to complete this course soon!
~imatheussm