1

So here is my code, I think I'm going wrong because the BITMAPFILEHEADER and BITMAPINFOHEADER are not being updated, so there are too many bytes being written to the output file, am I right with this? Also, how can I update them?

/**
* Copies a BMP piece by piece, just because.
*/

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#include "bmp.h"

int main(int argc, char *argv[])
{
// ensure proper usage
if (argc != 4)
{
    fprintf(stderr, "Usage: ./resize n infile outfile\n");
    return 1;
}

// remember resize factor
int n = atoi(argv[1]);

// remember filenames
char *infile = argv[2];
char *outfile = argv[3];

// open input file 
FILE *inptr = fopen(infile, "r");
if (inptr == NULL)
{
    fprintf(stderr, "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 5;
}

int old_biWidth = bi.biWidth;
int old_biHeight = bi.biHeight;

// determine padding for scanlines
int old_padding = (4 - (old_biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

bi.biWidth *= n;
bi.biHeight *= n;

int new_padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

bi.biSizeImage = ((sizeof(RGBTRIPLE) * bi.biWidth) + new_padding) * abs(bi.biHeight);
bf.bfSize = bi.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

// 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(old_biHeight); i < biHeight; i++)
{
    // iterate over pixels in scanline
    for (int j = 0; j < old_biWidth; j++)
    {
        // temporary storage
        RGBTRIPLE triple;

        // read RGB triple from infile
        fread(&triple, sizeof(RGBTRIPLE), 1, inptr);

        for(int h = 0; h < n; h++)
        {
            // write RGB triple to outfile
            fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
            j++;
        }
    }

    // skip over padding, if any
    fseek(inptr, old_padding, SEEK_CUR);

    // then add it back (to demonstrate how)
    for (int k = 0; k < new_padding; k++)
    {
        fputc(0x00, outptr);
    }
}

// close infile
fclose(inptr);

// close outfile
fclose(outptr);

// success
return 0;
}
1

There's absolutely nothing wrong with your header output. However, the generated image data is flawed.

There are two problems. First, j is being incremented both in the outer for loop setup and inside the loop, so it is missing about half of the necessary processing.

Second, there is no code in the program to handle the vertical scaling.

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .