I hit a wall a while ago on 'more comfortable' and since downgrading have been trying attempts on this for a few days - fully aware i'll be missing something, either in my logic or implementation but at this point my thinking is so misty. Any help and clarity would be totally brilliant. The output image is not correct - Where am i going wrong?
large.bmp f=2 output looks like:
smiley.bmp f=2 output looks like:
My truncated pseudocode is as follows:
- loop over height one by one
- loop through input pixels one by one, skipping the padding
- add f (resize factor) number of pixels into a new array
- write that array to the destination f (resize factor) times, adding any padding
My code is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "bmp.h"
int main(int argc, char *argv[])
{
// ensure proper usage
if (argc != 4)
{
fprintf(stderr, "Usage: ./resize [scale factor] infile outfile\n");
return 1;
}
// remember filenames
char *infile = argv[2];
char *outfile = argv[3];
// remember factor if between 100.0 and 0.1
float value = atof(argv[1]);
float f = roundf(10 * value) / 10;
printf("%f\n", f);
if (f>100||f<0.1)
{
fprintf(stderr, "Usage: ./resize [scale factor BETWEEN 0.1 and 100.0] infile outfile\n");
return 1;
}
// 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;
}
//define input dimension variables
int inWidth = bi.biWidth;
printf("%i", inWidth);
int inHeight = abs(bi.biHeight);
printf("%i", inHeight);
//define output dimension variables
bi.biWidth = round(inWidth*f);
bi.biHeight = round(inHeight*f);
// determine padding for scanlines
int padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
// determine padding for scanlines
int oldPadding = (4 - (inWidth * sizeof(RGBTRIPLE)) % 4) % 4;
// add padding to biSizeImage calculations
bi.biSizeImage = abs(bi.biHeight) * (bi.biWidth+padding);
// calculate bfSize which is total file size of bmp:
// - biSizeImage*RGBTRIPLE size - pixels including padding
// - biSize - info header size
// - bfOffBits - bitmapfile header and infoheader size
bf.bfSize = (bi.biSizeImage*sizeof(RGBTRIPLE)) + bf.bfOffBits;
// write outfile's BITMAPFILEHEADER
fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr);
// write outfile's BITMAPINFOHEADER
fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr);
// size of temporary storage
int RGBTRIPLE_sizeof = sizeof(RGBTRIPLE);
// allocate memory
RGBTRIPLE * pixString = malloc(RGBTRIPLE_sizeof*bi.biWidth);
// temporary storage
RGBTRIPLE triple;
// iterate over infile's scanlines
for (int i = 0; i < inHeight; i++)
{
// iterate over pixels in scanline
for (int j = 0; j < inWidth; j++)
{
// read RGB triple from infile
fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
// skip over padding, if any
fseek(inptr, oldPadding, SEEK_CUR);
int c=0;
for (int y = 0; y<f; y++){
pixString[c]=triple;
c++;
}
}
for (int s = 0; s<f; s++){
for (int z = 0; z<bi.biWidth;z++){
triple = pixString[z];
fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
}
// then add it back
for (int k = 0; k < padding; k++)
{
fputc(0x00, outptr);
}
}
}
// close infile
fclose(inptr);
// close outfile
fclose(outptr);
// success
return 0;
}