I'm having some trouble with the resize problem, specifically copying the scanline of interest so it can be duplicated vertically. I've been working on this for awhile and I think I'm on the right track (I hope?), but I can't seem to figure out where I'm going wrong. Any pointers (haha), debugging tips, or general nudges in the right direction would be helpful.
Edit: The program compiles and runs, but the picture is not what I want it to be.
/**
* resize.c
*
* Computer Science 50
* Problem Set 4
*
* Resizes a bmp image
**/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdbool.h>
#include <string.h>
#include "bmp.h"
//prototypes
bool isNumber(char* arr);
int main (int argc, char* argv[])
{
// ensure proper usage
if (argc != 4 || !isNumber(argv[1]))
{
printf("Usage: ./resize n infile outfile\n");
return 1;
}
// remember n
int n = atoi(argv[1]);
// ensure n is positive number less than or equal to 100
if (n < 1 || n > 100)
{
printf("n must be greater than 0 and no larger than 100.\n");
return 2;
}
// remember filenames
char* infile = argv[2];
char* outfile = argv[3];
// open input file
FILE* inptr = fopen(infile, "r");
if (inptr == NULL)
{
printf("Sorry, %s could not be opened.\n", argv[2]);
return 3;
}
// open output file
FILE* outptr = fopen(outfile, "w");
if (outptr == NULL)
{
fclose(inptr);
fprintf(stderr, "Could not create %s.\n", argv[3]);
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);
fseek(inptr, 0, SEEK_SET);
// 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 5;
}
// create new file header for outfile
BITMAPFILEHEADER bf_outfile;
fread(&bf_outfile, sizeof(BITMAPFILEHEADER), 1, inptr);
// create new info header for outfile
BITMAPINFOHEADER bi_outfile;
fread(&bi_outfile, sizeof(BITMAPINFOHEADER), 1, inptr);
// update outfile width and height
bi_outfile.biWidth = bi.biWidth * n;
bi_outfile.biHeight = bi.biHeight * n;
// determine padding of infile
int padding_infile = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
// determine padding for outfile
int padding_outfile = (4 - (bi_outfile.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
// update outfile image size
bi_outfile.biSizeImage = ((bi_outfile.biWidth * sizeof(RGBTRIPLE)) + padding_outfile) * abs(bi_outfile.biHeight);
// update outfile file header
bf_outfile.bfSize = bi_outfile.biSizeImage + bf.bfOffBits;
// write outfile's BITMAPFILEHEADER
fwrite(&bf_outfile, sizeof(BITMAPFILEHEADER), 1, outptr);
// write outfile's BITMAPINFOHEADER
fwrite(&bi_outfile, sizeof(BITMAPINFOHEADER), 1, outptr);
// memory to remember outfile's scanline
RGBTRIPLE* scanline = malloc(bi_outfile.biWidth);
// iterate over infile's scanlines
for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
{
// reset scanline_place
int scanline_place = 0;
// iterate over pixels in infile scanline
for (int j = 0; j < bi.biWidth; j++)
{
// temporary storage
RGBTRIPLE triple;
// read RGB triple from infile
fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
// copy triple to new scanline
int horizontal_copies = 0;
while (horizontal_copies < n)
{
scanline[scanline_place] = triple;
scanline_place++;
horizontal_copies++;
}
}
// write new scanlines
int vertical_copies = 0;
while (vertical_copies < n)
{
fwrite(&scanline, bi_outfile.biWidth * sizeof(RGBTRIPLE), 1, outptr);
// put in padding, if any
int padding = 0;
while (padding < padding_outfile)
{
fputc(0x00, outptr);
padding++;
}
vertical_copies++;
}
// skip over infile padding, if any
fseek(inptr, padding_infile, SEEK_CUR);
}
// free memory
free(scanline);
// close infile
fclose(inptr);
// close outfile
fclose(outptr);
// that's all folks
return 0;
}
bool isNumber(char* arr)
{
for (int i = 0, n = strlen(arr); i < n; i++)
{
if(isalpha(arr[i]))
{
return false;
}
}
return true;
}