1

I've been stuck on this for several days. I'm trying to resize the provided smiley.bmp with n=4 as that file shouldn't require padding. I get a new .bmp image of the correct size (32x32), but the bottom 3/4 of the new image's canvas isn't filled (i.e. it was apparently only resized horizontally).

My code is below. The loop involving 'j' is my attempt to iterate over each scan line n number of times. Thank you in advance for the help. :)


// Resizes 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 n infile outfile\n");
        return 1;
    }

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

    // set image multiplier value n from user input on command line
    int n = atoi(argv[1]);

    // 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)
    {
        fclose(inptr);
        fprintf(stderr, "Could not create %s.\n", outfile);
        return 3;
    }

    // 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 4;
    }

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

    // output a few variable values to the screen
    printf("infile bi.biSizeImage is %d", bi.biSizeImage);
    printf("\ninfile bf.bfSize is %d", bf.bfSize);
    printf("\nsize of BITMAPFILEHEADER from infile is %lu", sizeof(BITMAPFILEHEADER));
    printf("\nsize of BITMAPINFOHEADER from infile is %lu", sizeof(BITMAPINFOHEADER));

    // storing some original variable values, and setting new variables for outfile
    int biwidthorig = bi.biWidth;
    int biheightorig = bi.biHeight;
    bi.biWidth = bi.biWidth * n;
    bi.biHeight = bi.biHeight * n;
    int newfilepadding = (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);

    // barf many more variable values to the screen
    printf("\noutfile bi.biSizeImage is %d", bi.biSizeImage);
    printf("\noutfile bf.bfSize is %d", bf.bfSize);
    printf("\nn is %d", n);
    printf("\npadding is %d", padding);
    printf("\nnewfilepadding is %d", newfilepadding);
    printf("\nbiwidthorig is %d", biwidthorig);
    printf("\nbi.biWidth is %d", bi.biWidth);
    printf("\nbiheightorig is %d", biheightorig);
    printf("\nbi.biHeight is %d", bi.biHeight);
    printf("\nsize of BITMAPFILEHEADER to output is %lu", sizeof(BITMAPFILEHEADER));
    printf("\nsize of BITMAPINFOHEADER to output is %lu", 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(biheightorig); i < biHeight; i++)
    {
        // iterate over pixels in scanline n number of times
        for(int j = 1; j <= n; j++)
            for (int k = 0; k < biwidthorig; k++)
            {
                // temporary storage
                RGBTRIPLE triple;

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

                // write RGB triple to outfile n number of times for each pixel
                for(int l = 1; l <= n; l++)
                    fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
            }

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

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

    // a couple more variables to dump to screen
    printf("\nsize of RGBTRIPLE is %lu", sizeof(RGBTRIPLE));
    printf("\nvalue of SEEK_CUR is %d", SEEK_CUR);
    printf("\n");

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // success
    return 0;
}

1 Answer 1

1

Looks like most of the pieces are there. Since you're getting 1/4 of the image filled, that kinda says the file size is right. ;-)

Now, the j loop is there to repeat the rows j times to produce the vertical scaling. But the image only has the original height and (I believe) the last 3/4 are copies of the last line. That means that the lines aren't being duplicated correctly.

Does the code go back to the beginning of each line in the input file between processing loops? Or does it just continue through the input file without actually reprocessing each line the correct number of times?

Oh, by the way, is each line getting the right amount of padding?

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

1
  • This was it. I needed to move back to the start of the row in my infile for all but the final iteration of that row. I haven't had a chance to look at any padding issues yet. Thank you! :) Jul 25, 2018 at 14:00

You must log in to answer this question.

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