0

I saw others posted about the same phenomena I am experiencing, but none of their solutions were what I needed. n = 1 works perfectly. This is large.bmp with an n = 2.


./resize 2 small.bmp large.bmp


I realize the first line of my output is correct, but after trying for so long and even restarting I cannot find the bug causing this. Thank you in advance.

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

// remember resize factor termed n
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;
}

// store initial h & w, calculate outfile h & w

int inputHeight = abs(bi.biHeight);
int inputWidth = bi.biWidth;
int outbiHeight = abs(bi.biHeight * n);
int outbiWidth = bi.biWidth * n;

// calculate infile and outfile padding IN BYTES

int inPadding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
int outPadding = (4 - (outbiWidth * sizeof(RGBTRIPLE)) % 4) % 4;

// write outfile's BITMAPFILEHEADER
if (n == 1)
{
    fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr);
}
else
{

    bf.bfSize = (outbiHeight * outbiWidth * sizeof(RGBTRIPLE)) + outPadding + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
    fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr);

}

// write outfile's BITMAPINFOHEADER
if (n == 1)
{

    fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr);

}
else
{

    bi.biHeight = 0 - outbiHeight;
    bi.biWidth = outbiWidth;
    bi.biSizeImage = (outbiHeight * outbiWidth * sizeof(RGBTRIPLE)) + outPadding;

    fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr);

}

// iterate over infile's scanlines

for (int i = 0; i < inputHeight; i++)
{

    // iterate over pixels in scanline

    for (int j = 0; j < inputWidth; j++)
    {
        // temporary storage
        RGBTRIPLE triple;

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

        // write triple to outfile n times
        for (int k = 0; k < n; k++)
        {

            fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);

        }

    }

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

    for (int k = 0; k < outPadding; k++)
    {

        fputc(0x00, outptr);

    }

    for (int l = 0; l < (n - 1); l++)
    {

        int seekOffset = -((sizeof(RGBTRIPLE) * outbiWidth) + inPadding);

        for (int j = 0; j < inputWidth; j++)
        {

            fseek(inptr, seekOffset, SEEK_CUR);

            // temporary storage
            RGBTRIPLE repeatTriple;

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

            // write triple to outfile n times
            for (int k = 0; k < n; k++)
            {

                fwrite(&repeatTriple, sizeof(RGBTRIPLE), 1, outptr);

            }

        }

        // skip over padding, if any
        fseek(inptr, inPadding, SEEK_CUR);
        for (int p = 0; p < outPadding; p++)
        {

            fputc(0x00, outptr);

        }


    }


}

// close infile
fclose(inptr);

// close outfile
fclose(outptr);

// success
return 0;

}

0

Since it works for n=1 and for the first line when n!=1, that says that there's a problem with the code that handles multiple copies of each line. Looking at the raw data, the image data section contains data from the header section. That says that the code is moving the file pointer too far back in the input file.

Let's take a close look at the relevant code:

for (int l = 0; l < (n - 1); l++)
{
    int seekOffset = -((sizeof(RGBTRIPLE) * outbiWidth) + inPadding);
    for (int j = 0; j < inputWidth; j++)
    {
        fseek(inptr, seekOffset, SEEK_CUR);
...

There are two issues with this code. First, look at the line that sets the value for seekoffset. It's setting the distance to move in the input file. So, why does the calculation use outbiwidth, the width of the line in the output file?

Second, look at where the fseek is placed in the code. That fseek will be executed for every pixel that's processed. It should only be processed once each line.

On a side note, you should work on simplifying the code. Here are some examples.

The code has separate blocks to handle the case where n=1 and where n!=1. Only one code block is needed, and it should be able to calculate header data fields no matter what n is. BTW, there are issues in the header calculations when n!=1.

Next, there is a block of code to process the first copy of a line of pixels and then another to process additional lines. Again, duplicating code.

Whenever code is duplicated exactly, or nearly exactly, it should be a red flag that there is unnecessary redundant code and should be examined to see if it can be simplified.

This should get you going again.

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

You must log in to answer this question.

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