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 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
/**
* resize.c
*
* Computer Science 50
* Problem Set 4
*
* Resizes the file whose name is passed to it as a commandline argument.
*/
#include <stdio.h>
#include <stdlib.h>
#include "bmp.h"
int main(int argc, char* argv[])
{
// ensure proper usage
if (argc != 4)
{
printf("Usage: ./resize n infile outfile\n");
return 1;
}
// remember filenames
char* infile = argv[2];
char* outfile = argv[3];
// change n into a number so we can use it as such
int n = atoi(argv[1]);
if (n <= 0 || n > 100)
{
printf("The value provided as the size must be that of a positive integer less than or equal to 100!\n");
return 2;
}
// open input file
FILE* inptr = fopen(infile, "r");
if (inptr == NULL)
{
printf("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;
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;
}
//remember the old padding
int padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
// remember dimensions of resized image
int img_height = bi.biHeight;
int img_width = bi.biWidth;
// calculate dimensions of resized image
bi.biHeight *= n;
bi.biWidth *= n;
int resized_height = bi.biHeight;
int resized_width = bi.biWidth;
// determine scanline padding
int new_padding = (4 - (resized_width * sizeof(RGBTRIPLE)) % 4) % 4;
// update header info
bi.biSizeImage = ((resized_width * sizeof(RGBTRIPLE) + new_padding) * abs(resized_height));
bf.bfSize = bi.biSizeImage + (sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER));
// write outfile's BITMAPFILEHEADER
fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr);
// write outfile's BITMAPINFOHEADER
fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr);
// iterate over infile's scanlines
for (int i = 0, biHeight = abs(img_height); i < biHeight; i++)
{
// iterate over pixels in scanline
for (int j = 0; j < img_width; j++)
{
// temporary storage
RGBTRIPLE triple;
// read RGB triple from infile
fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
for (int index = 0; index <= n - 1; index++)
{
fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
}
}
// add new padding (if any must be added)
for (int k = 0; k < new_padding; k++)
{
fputc(0x00, outptr);
}
// skip over old padding, if any
fseek(inptr, padding, SEEK_CUR);
// iterate over images' widths and heights to resize vertically
for (int l = 0; l < img_width; l++)
{
// storage for the triples data
RGBTRIPLE triple;
// read from the infile and store in triple
fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
for (int m = 0; m < biHeight; m++)
{
for (int index = 0; index <= n - 1; index++)
{
fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
}
}
for (int k1 = 0; k1 < new_padding; k1++)
{
fputc(0x00, outptr);
}
fseek(inptr, -padding, SEEK_CUR);
}
}
// close infile
fclose(inptr);
// close outfile
fclose(outptr);
// that's all folks
return 0;
}
|