I'm struggling a bit with resize. I think my headers work correctly as I do get a correct size output, but after the first horizontal line everything goes wack.
My guess is that the fault lies in how I use the fseek function as I'm not sure I understand it completely yet. But there might also be some fault in my loops as well.
Here's the code:
// Copies a BMP file #include <stdio.h> #include <stdlib.h> #include "bmp.h" int main(int argc, char *argv[]) { // ensure proper usage if (argc != 4) { fprintf(stderr, "Usage: copy scale infile outfile\n"); return 1; } // remember filenames char *infile = argv[2]; char *outfile = argv[3]; // remember the scale int scale = atoi(argv[1]); if (scale < 0 || scale > 100) { fprintf(stderr, "Scale should be between 0 and 100\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, bfOut; fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr); bfOut = bf; // read infile's BITMAPINFOHEADER BITMAPINFOHEADER bi, biOut; fread(&bi, sizeof(BITMAPINFOHEADER), 1, inptr); biOut = bi; // 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; } // calculate resized height and width for the outfile header biOut.biHeight = bi.biHeight * scale; biOut.biWidth = bi.biWidth * scale; // determine padding for scanlines int padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4; // outfile padding int outPadding = (4 - (biOut.biWidth * sizeof(RGBTRIPLE)) % 4) % 4; // calculate new image size for the outfile's BITMAPINFOHEADER biOut.biSizeImage = ((sizeof(RGBTRIPLE) * biOut.biWidth) + outPadding) * abs(biOut.biHeight); // calculate new file size for the outfile's BITMAPFILEHEADER bfOut.bfSize = biOut.biSizeImage + sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER); // write outfile's BITMAPFILEHEADER fwrite(&bfOut, sizeof(BITMAPFILEHEADER), 1, outptr); // write outfile's BITMAPINFOHEADER fwrite(&biOut, sizeof(BITMAPINFOHEADER), 1, outptr); // iterate over infile's scanlines for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++) { // iterate over scanlines resize factor - 1 times for (int v = 0; v < scale - 1; v++) { // 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 multiplied by the resize factor for (int t = 0; t < scale; t++) { // write RGB triple to outfile fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr); } } // write padding to outfile for (int k = 0; k < outPadding; k++) { fputc(0x00, outptr); } // reset stream pointer for next scanline fseek(inptr, -((biOut.biWidth * sizeof(RGBTRIPLE)) + outPadding), SEEK_CUR); } // 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 multiplied by the resize factor for (int t = 0; t < scale; t++) { // write RGB triple to outfile fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr); } } // write padding to outfile for (int k = 0; k < outPadding; k++) { fputc(0x00, outptr); } // skip over padding, if any fseek(inptr, padding, SEEK_CUR); } // close infile fclose(inptr); // close outfile fclose(outptr); // success return 0; }