I have looked through many of the same questions but come up with no answers.
I am solely focusing at the moment on changing the headers and have tried to get calculations correct but something must be wrong as any image is invalid or unsupported when you try to open it. This also means I can't use peek to look at headers. I have looked at the values of the changed variables using printf and they aren't garbage values, they seem mostly correct, although I'm not sure that the padding is always right. Any help appreciated. Here's my code so far:
// remember filenames
double f = atof(argv[1]);
char *infile = argv[2];
char *outfile = argv[3];
//ensure float within range
if (f > 100.0 || f < 0.0)
{
fprintf(stderr, "Factor must be between 0.0 and 100.0\n");
return 2;
}
// open input file
FILE *inptr = fopen(infile, "r");
if (inptr == NULL)
{
fprintf(stderr, "Could not open %s.\n", infile);
return 3;
}
// open output file
FILE *outptr = fopen(outfile, "w");
if (outptr == NULL)
{
fclose(inptr);
fprintf(stderr, "Could not create %s.\n", outfile);
return 4;
}
// read infile's BITMAPFILEHEADER
BITMAPFILEHEADER bf;
BITMAPFILEHEADER new_bf = bf;
fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr);
// read infile's BITMAPINFOHEADER
BITMAPINFOHEADER bi;
BITMAPINFOHEADER new_bi = 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 5;
}
// change header sizes
new_bi.biWidth = (bi.biWidth * f);
new_bi.biHeight = (bi.biHeight * f);
// determine padding for scanlines
int padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
int new_padding = (4 - (new_bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
// change header sizes
new_bi.biSizeImage = (new_bi.biWidth * abs(new_bi.biHeight) * sizeof(RGBTRIPLE)) + (new_padding * abs(new_bi.biHeight));
new_bf.bfSize = (new_bi.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER));
// write outfile's BITMAPFILEHEADER
fwrite(&new_bf, sizeof(BITMAPFILEHEADER), 1, outptr);
// write outfile's BITMAPINFOHEADER
fwrite(&new_bi, sizeof(BITMAPINFOHEADER), 1, outptr);
// 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 outfile
fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
}
// skip over padding, if any
fseek(inptr, padding, SEEK_CUR);
// then add it back (to demonstrate how)
for (int k = 0; k < padding; k++)
{
fputc(0x00, outptr);
}
}
// close infile
fclose(inptr);
// close outfile
fclose(outptr);
// success
return 0;
}