0

My code is as follows:

/** * resize.c * * Computer Science 50 * Problem Set 4 * * Resize a BMP. */ #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 filenames and n int n = atoi(argv[1]); char* infile = argv[2]; char* outfile = argv[3]; // 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; } // write outfile's BITMAPINFOHEADER BITMAPINFOHEADER biout = bi; biout.biWidth = bi.biWidth * n; biout.biHeight = bi.biHeight * n; biout.biSizeImage = (((4 - (biout.biWidth * sizeof(RGBTRIPLE)) % 4) % 4 ) * abs(biout.biHeight)) + (biout.biWidth * abs(biout.biHeight) * 3); fwrite(&biout, sizeof(BITMAPINFOHEADER), 1, outptr); // write outfile's BITMAPFILEHEADER BITMAPFILEHEADER bfout = bf; bfout.bfSize = biout.biSizeImage + 14 + 40; fwrite(&bfout, sizeof(BITMAPFILEHEADER), 1, outptr); // determine padding for scanlines int padding = (4 - (biout.biWidth * sizeof(RGBTRIPLE)) % 4) % 4; // iterate over infile's scanlines for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++) { // Writes scanline n times for (int l = 0; l < n; l++) { // moves SEEK_CUR if repeating the line vertically if (l > 0) { fseek(inptr, ((((4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4) + bi.biWidth * 3) * -1), 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 n times for (int k = 0; k < n; k++) { 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); // that's all folks return 0; } 

After running resize.c with ./resize 2 small.bmp large.bmp, I was unable to open the large.bmp created as there was an error. So going back to my code, I ran gdb and went line by line to find out what exactly is happening. I found out that after the second iteration of for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++) (i = 1 at this point), at line 98 (for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)) executes correctly and reads triple as 00FF00. However the moment the next line executes, triple becomes 000000 instead.

Why is this so? And if there is anything I missed out, please do give me a clue! Coming here is a last resort for me but I have been stuck here for several days so thank you for reading this. :)

1 Answer 1

1

Your triple didn't change, it moved. You have two significant problems. Your headers are wrong and your padding is wrong. You need to get the headers right before moving on to the images. I recommend that you get everything working for n=1 before moving on to n=2. When n=1, the input and output files should be identical. xxd and peek will be your best friends. ;-)

The header problem is an easy fix. There are two headers - in what order do they appear in the file?

Padding: The padding for the output file is not necessarily the same as the padding for the input file. Both paddings need to be calculated, based on the header data for that file.

This will get you going towards solving most of your problems. You might also consider calculating the inpadding and the outpadding only once each, storing the values in those vars and then use the vars to calculate the headers and to process the image.

If this answers your question, please click on the check mark to accept. Let's keep up on forum housekeeping. ;-)

1
  • Thank you very much :) The advice for creating two padding made my code much neater too! Commented Feb 8, 2016 at 7:34

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.