1

I've been stuck with Resize (Less) using the "Rewrite" method for days but just can't seem to figure out what's wrong with my code. My code compiled OK, and has no problem with n=1. But it can't resize for n=2 and above. Would be great if anyone could please let me know what's 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: copy infile outfile\n");
        return 1;
    }

    // remember filenames
    int n = atoi(argv[1]);
    char *infile = argv[2];
    char *outfile = argv[3];


    if (n < 0 || n > 100)
    {
        printf("Number must be positive and less than or equal to 100 lah!\n");
        return 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);

    //updating new headers
    int new_bibiWidth = bi.biWidth*n;
    int new_bibiHeight = bi.biHeight*n;
    int new_padding = (((4 - (new_bibiWidth) * sizeof(RGBTRIPLE)) % 4) % 4);
    bi.biSizeImage = ((sizeof(RGBTRIPLE) * new_bibiWidth) + new_padding) * abs(new_bibiHeight);
    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);


    //temporary storage for storing n times pixels
    RGBTRIPLE outfilerow[new_bibiWidth];

    // resizing horizontally and vertically
    for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
    {
        int q = 0;
        //iterate over infile's pixels
        for (int j = 0; j < bi.biWidth; j++)
        {

            // temporary storage for reading from infile
            RGBTRIPLE triple;

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

            //write infile's pixels to array n times
            for (int k = 0; k < n; k++)
            {
                outfilerow[q] = triple;
                q++;
            }
        }


        for (int l = 0; l < n; l++)
        {
            for(int m = 0; m < new_bibiWidth; m++)
            {
                //write from array to outfile
                fwrite(&outfilerow[m], sizeof(RGBTRIPLE), 1, outptr);
            }


            for (int p = 0; p < new_padding; p++)
            {
                //write new padding
                fputc(0x00, outptr);
            }

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

    }

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // success
    return 0;
}
1

So close, but I think you might be looking in the wrong place.

Have you verified that your header values are all correct in the output file????????? Those values control how the image data is displayed.

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

[EDIT - now that Nic has found the problem.] This doesn't happen very often, but it's misleading when it does. He thought that the problem was in how the image data was being built, but in reality, the image data was perfect. The problem was in the header data. Since biWidth, and to some degree, biHeight, were incorrectly calculated, it was displaying the image incorrectly. It was building an image with the wrong width, so it was actually treating live pixel data as padding. Then, the padding was being processed as live pixel data. That shifted pixel data the wrong distance, so it produced an assortment of colors in the pixels.

The bottom line was that the header data caused the correct image data to be displayed incorrectly!

This is why it is emphasised to make sure the headers are correctly processed before focusing on the image data, and to actually look at the raw data, not just the displayed image!!!

And, take note. The padding for the input image and for the output image must be calculated for each. There is no guarantee that the padding for the two files will match. In fact, they're more likely to be different for any scaling factor other than 1.

2
  • Omg thanks for pointing me to the right direction, I've finally solved it by changing the header info! Thanks again!
    – Nic Moe
    Oct 2 '19 at 18:49
  • Glad to help. Now that you've figured it out, I'll go back and edit my answer. If you're happy, could you please accept the answer? Otherwise, it'll sit in the unanswered question pool forever.
    – Cliff B
    Oct 2 '19 at 20:50

You must log in to answer this question.

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