I'm having a hard time understanding pset4's resize. Although I understand the theory, it's difficult for me to turn it into a program.
I do understand that the scan line's total width must be a multiple of four, and I presume that it's the same formula used from copy.c.
I've watched the video, and I'm attempting to use the recopy method. In the video, Zamyla states that fseek is used to reset the file indicator. In my code, I've put another fseek after I add padding, but I suspect this isn't the proper place. If so, where would I put it?
Any other help for my code would also be greatly appreciated (especially towards the loops).
Here's my code.
/**
* copy.c
*
* Computer Science 50
* Problem Set 4
*
* Copies a BMP piece by piece, just because.
*/
#include <stdio.h>
#include <stdlib.h>
#include "bmp.h"
int main(int argc, char* argv[])
{
// ensure proper usage
if (argc != 4)
{
printf("Usage: ./copy n infile outfile\n");
return 1;
}
// remember arguments
int n = atoi(argv[1]);
char* infile = argv[2];
char* outfile = argv[3];
if (n < 1 || n > 100) {
printf("n must be between 1 - 100 \n");
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;
}
// update headers
BITMAPFILEHEADER new_bf = bf;
BITMAPINFOHEADER new_bi = bi;
new_bi.biWidth = bi.biWidth * n;
new_bi.biHeight = bi.biHeight * n;
int new_padding = ((4 - (new_bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4);
printf("%i, %i\n", bi.biWidth, new_bi.biWidth);
new_bi.biSizeImage = (new_bi.biWidth * abs(new_bi.biHeight) * 2) * sizeof(RGBTRIPLE) + new_padding;
new_bf.bfSize = new_bi.biSizeImage + sizeof(bf) + sizeof(bi);
// write outfile's BITMAPFILEHEADER
fwrite(&new_bf, sizeof(BITMAPFILEHEADER), 1, outptr);
// write outfile's BITMAPINFOHEADER
fwrite(&new_bi, sizeof(BITMAPINFOHEADER), 1, outptr);
// determine padding for scanlines
int padding = ((4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4);
printf("%i\n", new_padding);
// iterate over infile's scanlines
for (int i = 0, biHeight = abs(new_bi.biHeight); i < biHeight; i++)
{
for (int j = 0; j < n; j++) {
// iterate over pixels in scanline
for (int k = 0; k < new_bi.biWidth; k++)
{
// temporary storage
RGBTRIPLE triple;
// read RGB triple from infile
fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
for (int l = 0; l < n; l++)
{
// write RGB triple to outfile
fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
}
}
// skip padding
fseek(inptr, padding, SEEK_CUR);
// adds padding if needed
for (int k = 0; k < new_padding; k++)
{
fputc(0x00, outptr);
}
// reset to beginning of line
fseek(inptr, -(bi.biWidth * sizeof(RGBTRIPLE)), SEEK_CUR);
}
}
// close infile
fclose(inptr);
// close outfile
fclose(outptr);
// that's all folks
return 0;
}
When I run ./resize 5 small.bmp student.bmp
, the result is this:
biSizeImage
andbfSize
.