I have the dimensions of the image right, and I have the horizontal scaling working, but I can't figure out how to get the vertical pixels to scale correctly. I've watched the walkthrough repeatedly, but I can't figure out what I need to do.

UPDATE: I'm using the recopy method, yet I'm not sure where I'm going wrong still. It's most likely in the part where I send the cursor back, though it could be somewhere else.

UPDATE 2: I was apparently sending the cursor too far back, yet when I fixed it, problems still persist. I think the cursor is fine for the most part, but whatever error there still is, I'm not sure.

Here is my code:

 * Copies a BMP piece by piece, just because.

#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 factor infile outfile\n");
        return 1;

    // remember filenames
    int factor = atoi(argv[1]);
    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;
    int oldpadding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

    bi.biWidth *= factor;
    bi.biHeight *= factor;

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

    bi.biSizeImage = ((sizeof(RGBTRIPLE) * bi.biWidth) + 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(bi.biHeight); i < biHeight; i++)
        for (int a = 0; a < factor - 1; a++)
            // iterate over pixels in scanline
            for (int j = 0; j < bi.biWidth; j++)
                // temporary storage
                RGBTRIPLE triple;

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

                // Scale rows
                for (int b = 0; b < factor; b++)
                    // write RGB triple to outfile
                    fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);

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

            for (int k = 0; k < padding; k++)
                fputc(0x00, outptr);

            int seek = bi.biWidth * sizeof(RGBTRIPLE) + oldpadding;
            fseek(inptr, -seek, SEEK_CUR);

        int seek = bi.biWidth * sizeof(RGBTRIPLE) + oldpadding;
        fseek(inptr, seek, SEEK_CUR);


    // close infile

    // close outfile

    // success
    return 0;

If anyone could help, that would be great.

  • Answer edited with comment on new version. Apr 29 '17 at 12:48

Review the pseudocode from the walkthrough:

psuedocode: "recopy" method

for each row
     for n-1 times
          write pixels, padding to outfile
          send infile cursor back
     write pixels, padding to outfile
     skip over infile padding

The pseudocode for this program:

for each row (i loop)
     for factor times (a loop)
          write pixels to outfile
     skip over infile padding
     write padding to outfile

If you follow the walthrough code, you need to

  1. write the outfile padding at the end of each (new) row (ie each iteration of a).
  2. be at the beginning of the line for each iteration of a (send infile cursor back).
  3. only skip over the infile padding once for each infile row.

AFTER CODE EDIT: A seek too far. The j loop reads only pixels (not padding). This int seek = abs(bi.biWidth) * sizeof(RGBTRIPLE) + padding; is rewinding over all the pixels plus the new padding.

  • Personally I found that fseek tended to dislike negative numbers for some reason, even though nothing about fseeking backwards should really be an issue. I decided to use fpos_t object and fgetpos / fsetpos to achieve the same result as you are seeking (no pun intended) right now.
    – Coby Z
    Jul 15 '17 at 23:30

You must log in to answer this question.

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