I'm having trouble rewriting the file headers here. It works for a resize factor of 1, but no other resize factor. What am I doing wrong?

// Copies a BMP file

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

#include "bmp.h"

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

    //define user-inputted multiplier
    int n = atoi(argv[1]);

    // ensure positive integer less than or equal to 100

    if (n < 1 || n > 100)
        fprintf(stderr, "Multiplier must be a positive integer less than or equal to 100\n");
        return 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 2;

    // open output file
    FILE *outptr = fopen(outfile, "w");
    if (outptr == NULL)
        fprintf(stderr, "Could not create %s.\n", outfile);
        return 3;

    // read infile's BITMAPFILEHEADER
    fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr);

    // read infile's BITMAPINFOHEADER
    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)
        fprintf(stderr, "Unsupported file format.\n");
        return 4;

    // make bitmap headers for outfile

    bf_out = bf;
    bi_out = bi;

    // change BITMAPINFOHEADER width and height for outfile
    bi_out.biWidth *= n;
    bi_out.biHeight *= n;

    // determine padding for scanlines
    int padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
    int padding_out = (4 - (bi_out.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

    // change biSizeImage
    bi_out.biSizeImage = ((bi_out.biWidth * sizeof(RGBTRIPLE)) + padding_out) * abs(bi_out.biHeight);

    // change bfSize
    bf_out.bfSize = bi_out.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

    // write outfile's BITMAPFILEHEADER
    fwrite(&bf_out, sizeof(BITMAPFILEHEADER), 1, outptr);

    // write outfile's BITMAPINFOHEADER
    fwrite(&bi_out, 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
            for (int k = 0; k < n; k++)
                fread(&triple, sizeof(RGBTRIPLE), 1, inptr);

            // write RGB triple to outfile
            fwrite(&triple, sizeof(RGBTRIPLE), n, 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

    // close outfile

    // success
    return 0;
  • Why do you say the header is wrong? It worked fine for me. Are you sure that you recompiled it before running the latest code?
    – Cliff B
    Jul 13 '18 at 5:51
  • Definitely recompiled the version above before running. It works for a resize factor of 1, but not 2, 3, etc. It generates a new .bmp file but it cannot be opened and I'm getting an error message that it's not a valid image file.
    – Ryan G
    Jul 15 '18 at 1:13
  • Have you used the peek tool to compare headers? How about the xxd tool to look at the raw digital data? It can tell you a lot and help you troubleshoot the issues! When you looked at the raw data in the files, what did you see that was wrong? Did you see any patterns in the bad data? Does it tell you anything?
    – Cliff B
    Jul 15 '18 at 8:11
  • It does look like from the code that you are repeating the height but not rescaling it. That would make the file unreadable or would open it with weird looking colors.
    – PXSOCS
    Jul 15 '18 at 11:18

There are several issues. First, there's no code at all for vertical scaling.

Second, the padding for the input file is being used for the output file.

Third, look at this code:

        // write RGB triple to outfile
        fwrite(&triple, sizeof(RGBTRIPLE), n, outptr);

The third parameter, n, is the number of sequential triples to be written, not the number of times to write the same triple.

Fixing these may end up causing new issues, but this will get you going.

But, I still can't find a problem with the headers. ;-)

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

  • I ended up figuring it out. You are right, there wasn't anything wrong with the headers. When I was getting back a .bmp file that was "invalid" it was because the scaling was wrong. I was under the incorrect assumption that a valid header would make a valid bmp file regardless of what else was going on in the code after the header.
    – Ryan G
    Jul 16 '18 at 15:39

You must log in to answer this question.

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