I've been trying to write a program that resizes bitmap files, but cannot for the life of me figure out why my file size in the output file is off.
I tried resizing with another program and it resizes a file from 486 bytes to 1,9kb with a factor of 2, whereas my code results in a file of 3,5kb. Please have a look at my code and I hope someone can point me in the right direction as to what is making my file so bloated.
PS: The resulting file has the correct dimensions and also looks alright, its just the file size that's not scaling correctly...
#include <stdio.h>
#include <stdbool.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "bmp.h"
bool is_valid_count(int argc);
bool is_valid_range(int fact);
bool is_valid_file_type(char *filename);
int main(int argc, char *argv[])
{
char *n = argv[1];
int resize_factor = atoi(n);
// validate
if (!is_valid_count(argc) ||
!is_valid_range(resize_factor) ||
!is_valid_file_type(argv[2]) ||
!is_valid_file_type(argv[3]))
{
printf("USAGE: run resize <resize-factor> <infile.bmp> <outfile.bmp>\n");
return 1;
}
// remember filenames
char *infile = argv[2];
char *outfile = argv[3];
// open input file
FILE *open_in_file = fopen(infile, "r");
if (open_in_file == NULL)
{
fprintf(stderr, "Could not open %s.\n", infile);
return 2;
}
// open output file
FILE *open_out_file = fopen(outfile, "w");
if (open_out_file == NULL)
{
fclose(open_in_file);
fprintf(stderr, "Could not create %s.\n", outfile);
return 3;
}
// read infile's BITMAPFILEHEADER
BITMAPFILEHEADER bitmap_file_header;
fread(&bitmap_file_header, sizeof(BITMAPFILEHEADER), 1, open_in_file);
// read infile's BITMAPINFOHEADER
BITMAPINFOHEADER bitmap_info_header;
fread(&bitmap_info_header, sizeof(BITMAPINFOHEADER), 1, open_in_file);
// ensure infile is (likely) a 24-bit uncompressed BMP 4.0
if (bitmap_file_header.bfType != 0x4d42 ||
bitmap_file_header.bfOffBits != 54 ||
bitmap_info_header.biSize != 40 ||
bitmap_info_header.biBitCount != 24 ||
bitmap_info_header.biCompression != 0)
{
fclose(open_out_file);
fclose(open_in_file);
fprintf(stderr, "Unsupported file format.\n");
return 4;
}
int padding_old = (4 - (bitmap_info_header.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
LONG old_biWidth = bitmap_info_header.biWidth;
// resize bitmap
bitmap_info_header.biHeight *= resize_factor;
bitmap_info_header.biWidth *= resize_factor;
int padding_new = (4 - (bitmap_info_header.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
bitmap_info_header.biSizeImage = ((sizeof(RGBTRIPLE) * bitmap_info_header.biWidth) + padding_new) * abs(bitmap_info_header.biHeight);
bitmap_file_header.bfSize = bitmap_info_header.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
// write outfile's BITMAPFILEHEADER & BITMAPINFOHEADER
fwrite(&bitmap_file_header, sizeof(BITMAPFILEHEADER), 1, open_out_file);
fwrite(&bitmap_info_header, sizeof(BITMAPINFOHEADER), 1, open_out_file);
// iterate over infile's scanlines
for (int i = 0, biHeight = abs(bitmap_info_header.biHeight); i < biHeight; i++)
{
for (int j = 0; j < resize_factor; j++)
{
// iterate over pixels in scanline
for (int k = 0; k < old_biWidth; k++)
{
// temporary storage
RGBTRIPLE triple;
// read RGB triple from infile
fread(&triple, sizeof(RGBTRIPLE), 1, open_in_file);
for (int l = 0; l < resize_factor; l++)
{
// write RGB triple to outfile
fwrite(&triple, sizeof(RGBTRIPLE), 1, open_out_file);
}
}
// add padding
for (int m = 0; m < padding_new; m++)
{
fputc(0x00, open_out_file);
}
if (j < resize_factor - 1)
{
fseek(open_in_file, -(old_biWidth * (int)sizeof(RGBTRIPLE)), SEEK_CUR);
}
}
// skip over padding, if any
fseek(open_in_file, padding_old, SEEK_CUR);
}
fclose(open_in_file);
fclose(open_out_file);
// success
return 0;
}
bool is_valid_count(int argc)
{
if (argc != 4)
{
printf("Incorrect number of arguments provided. Must be 3!\n");
return false;
}
return true;
}
bool is_valid_range(int fact)
{
if (fact < 1 || fact > 100)
{
printf("Range is invalid.Resize-factor has to be between 1 and 100! Was: %i\n", fact);
return false;
}
return true;
}
bool is_valid_file_type(char *filename)
{
const char *dot = strrchr(filename, '.');
const char *extension = ".bmp";
if (strcmp(dot, extension) != 0)
{
printf("Filetype not recognized: %s!\n", dot);
return false;
}
return true;
}
//FILE *open_in_file = fopen(infile, "r");
FILE *open_in_file = fopen(infile, "rb");
//FILE *open_out_file = fopen(outfile, "w");
FILE *open_out_file = fopen(outfile, "wb");
//for (int i = 0, biHeight = abs(bitmap_info_header.biHeight); i < biHeight; i++)
for (int i = 0, biHeight = abs(bitmap_info_header.biHeight)/resize_factor; i < biHeight; i++)