0

Hi, everyone!

I am currently finishing (after quite some thought and a lot of trial-and-error) the less comfortable version of the resize problem from pset4, which, as you probably know, resizes BMP images based on an integer command-line argument provided by the user.

While, as far as my tests have gone, the output files are graphically consistent with the stipulated resizing factors, on some scenarios the output file size does not match the expected bfSize.

check50 exposes this problem when using n = 2 and n = 3 on small.bmp.

I have looked through some questions; however, since I did not find so far anything related with the specific problem which I am going through, I'd love some assistance from you, guys!

If it is not asking too much, can you also give me a head-start on the changes I would have to make on my code in order to pass the more comfortable version of this problem? I know, of course, that I'd have to change resizingFactor from int to float; however, I think I'll have some trouble dealing with the decimal part of the number provided by the user.

Here follows my code:

// Copies a BMP file

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

#include "bmp.h"

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

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

    // remember resizing factor
    int resizingFactor = round(atoi(argv[1]));
    printf("Resizing Factor: %i\n\n", resizingFactor);

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

    // [DEBUG]
    printf("Initial biWidth: %d\nInitial biHeight: %d\nInitial biSizeImage: %u\n\nInitial bfSize: %u\n\n", bi.biWidth, bi.biHeight,
           bi.biSizeImage, bf.bfSize);

    // changing headers in accordance with the stipulated resizing factor
    LONG originalWidth = bi.biWidth, originalHeight = bi.biHeight;
    bi.biWidth = bi.biWidth * resizingFactor;
    bi.biHeight = bi.biHeight * resizingFactor;
    if ((bi.biWidth % 4) == 0)
    {
        bi.biSizeImage = bi.biWidth * abs(bi.biHeight) * 3;
    }
    else
    {
        bi.biSizeImage = 3 * (bi.biWidth + (4 - (bi.biWidth % 4))) * abs(bi.biHeight);
    }

    bf.bfSize = sizeof(bf) + sizeof(bi) + bi.biSizeImage;

    // [DEBUG]
    printf("Final biWidth: %d\nFinal biHeight: %d\nFinal biSizeImage: %u\n\nFinal bfSize: %u\n\n", bi.biWidth, bi.biHeight,
           bi.biSizeImage, bf.bfSize);
    printf("Original Width: %d\nOriginal Height: %d\n\n", originalWidth, originalHeight);

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

    // write outfile's BITMAPINFOHEADER
    fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr);

    // determine padding for scanlines
    int originalPadding = (4 - (originalWidth * sizeof(RGBTRIPLE)) % 4) % 4;
    int padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
    printf("Original Padding: %d\nFinal Padding: %d\n\n", originalPadding, padding);

    // iterate over infile's scanlines
    for (int i = 0, biHeight = abs(originalHeight); i < biHeight; i++)
    {
        for (int j = 0; j < resizingFactor; j++)
        {
            // iterate over pixels in scanline
            for (int k = 0; k < originalWidth; k++)
            {
                // temporary storage
                RGBTRIPLE triple;

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

                for (int l = 0; l < resizingFactor; l++)
                {
                    // write RGB triple to outfile
                    fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
                }
            }
            // add padding
            for (int m = 0; m < padding; m++)
            {
                fputc(0x00, outptr);
            }
            // going back to replicate the same line
            if (j < resizingFactor - 1)
            {
                fseek(inptr, -(originalWidth * (int)sizeof(RGBTRIPLE)), SEEK_CUR);
            }
        }
        // skip over padding, if any
        fseek(inptr, originalPadding, SEEK_CUR);
    }

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // success
    return 0;
}

Thank you in advance for the assistance provided. I hope to complete this course soon!

~imatheussm

1

First of all, you shouldn't have to have an if statement to calculate the image size depending on whether there is padding or not.

Next, think about this. biWidth is measured in pixels. Padding is measured in bytes. Exactly what are you multiplying by 3 and why?

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

2
  • Your comment was so useful! I did the math, rearranged some blocks of code (padding was in a posterior point of my code) and realized that bi.biSizeImage = ((3 * bi.biWidth) + padding) * abs(bi.biHeight);. I even managed to adapt my code to the more comfortable version of this problem! So thank you for your assistance, it was much appreciated. ~imatheussm – Igor Matheus Moreira Jul 30 '18 at 2:20
  • It's good to feel appreciated. :-D – Cliff B Jul 30 '18 at 2:29

You must log in to answer this question.

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