Hi Everyone,
I am currently working on problem set 4 for Harvard’s online CS50 course. I am working on a program that resizes a bmp image by a factor of N. N in entered along with an in-file and out-file in a command line argument. The program needs to calculate the header file for the out-file and write it to the out-file. It then needs to actually resize the image and, again, write to the out-file.
The first question I have relates to the header file, here is my code for calculating the header file:
bi2.biHeight = bi.biHeight *n;
bi2.biWidth = bi.biWidth *n;
int padding = (4 -(bi.biWidth * sizeof(RGBTRIPLE))%4)%4;
bi2.biSizeImage = (bi2.biWidth * sizeof(RGBTRIPLE) + padding) * abs(bi2.biHeight);
bf2.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + bi2.biSizeImage;
And here is my code for writing the new header file (bi2 and bf2) to the out-file:
fwrite(&bf2, sizeof(BITMAPFILEHEADER), 1, outptr);
fwrite(&bi2, sizeof(BITMAPINFOHEADER), 1, outptr);
Does my code look “OK” or do you see any issues???
At this point I need to actually resize the image. As far as I can tell there are 2 ways to go about this you either have to use an array to store each line you want to print repeatedly (and then you can just write it repeatedly) OR you have to move the pointer back in the input stream and repeat the read/resize/write process each time you need to print the row.
It is this that I am stuck on, first of all, I am not sure what system would be better for resizing the image, although I am leaning towards using an array, and regardless, I don’t even know where to begin when in implementing either.
So what I am asking for is, first of all, just a “double check” to make sure my header code makes sense. And second of all, a push in the right direction for actually resizing the image. Please keep in mind that this is for a course so I don’t simply want you to “fix” my code, I want to learn, and discover.
Thanks,
Joshua McDonald
Here is my complete code, if that helps:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
|
/****************************************************************************
* resize.c
*
* Computer Science 50
* Problem Set 4
*
* Resizes 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 filenames
char* nchar = argv[1];
char* infile = argv[2];
char* outfile = argv[3];
int timeswriten = 0;
//convert nchar to an int
int n = atoi (nchar);
if (n < 1 || n > 100)
{
printf("Please try again with a positive number less then 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, bf2;
fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr);
// read infile's BITMAPINFOHEADER
BITMAPINFOHEADER bi, bi2;
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;
}
bi2.biHeight = bi.biHeight *n;
bi2.biWidth = bi.biWidth *n;
int padding = (4 -(bi.biWidth * sizeof(RGBTRIPLE))%4)%4;
bi2.biSizeImage = (bi2.biWidth * sizeof(RGBTRIPLE) + padding) * abs(bi2.biHeight);
bf2.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + bi2.biSizeImage;
// write outfile's BITMAPFILEHEADER and BITMAPINFOHEADER
fwrite(&bf2, sizeof(BITMAPFILEHEADER), 1, outptr);
fwrite(&bi2, 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);
// Here is where I need to actually resise the image!!!!
// 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);
// that's all folks
return 0;
}
|