0

I am stuck with my pset4. When I try to resize the provided smiley.bmp (8X8 pixels) by the factor 4 everything is fine. Here, know padding has to be considered. The program's output is correct.

When I try to resize the provided small.bmp (3X3 pixels) by the factor 4 the program needs to consider padding, which it seems do not do correctly. I am not sure, if I have a mistake when reallocating the pointer in lines 118 to 130.

Maybe you see something I don't after staring at my code for ages.

Thanks :)

Cheers,

DOKMA

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

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

if (factor <= 0 || factor >= 100)
{
    printf("Please use positiv factor smaller or equal than hundred.\n");
    return 1;
}

// open input file 
FILE* inptr = fopen(infile, "r");
if (inptr == NULL)
{
    printf("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;
}

// create bitmap headers for the outfile. 
BITMAPFILEHEADER outptr_bf;
BITMAPINFOHEADER outptr_bi; 
outptr_bf = bf;
outptr_bi = bi;
outptr_bi.biWidth = bi.biWidth * factor;
outptr_bi.biHeight = bi.biHeight * factor;
outptr_bf.bfSize = outptr_bi.biSizeImage + 54;

// determine padding for scanlines for SizeImage calculation
int inptr_padding =  (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
int outptr_padding =  (4 - (outptr_bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

// Calculate file and image size
outptr_bf.bfSize = 54 + outptr_bi.biWidth * abs(outptr_bi.biHeight) * sizeof(RGBTRIPLE) 
+ abs(outptr_bi.biHeight) * outptr_padding;
outptr_bi.biSizeImage = (outptr_bi.biWidth * sizeof(RGBTRIPLE) + 
outptr_padding) * abs(outptr_bi.biHeight);

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

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

// iterate over infile's scanlines
for (int i = 0; i < abs(bi.biHeight); i++)
{
    for (int g = 0; g < factor; g++)
    {
        // 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);

            for (int h = 0; h < factor; h++)
            {
                // write RGB triple to outfile
                fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
            }

        }
        // skip padding
        fseek(inptr, inptr_padding, SEEK_CUR);

        // then ad padding to outfile
        if (outptr_padding > 0)
        { 
            for (int k = 0; k < outptr_padding; k++)
            {
                fputc(0x00, outptr);
            }
        }
        fseek(inptr, -(bi.biWidth * sizeof(RGBTRIPLE) + inptr_padding ), SEEK_CUR);
    }
    fseek(inptr, -(bi.biHeight * sizeof(RGBTRIPLE) + inptr_padding ), SEEK_CUR);
}

// close infile
fclose(inptr);

// close outfile
fclose(outptr);

// that's all folks
return 0;
}
1
  • Heey! I was wondering why it is necessary to have outptr_bf = bf; and outptr_bi = bi;. My program wasn't working and after a lot of search I found that a lot of people were doing this, so I tried and it worked, but I don't understand why. Could someone help me? @CliffB Commented Jun 24, 2016 at 17:20

1 Answer 1

1

You have two problems, neither is related to the padding. Look at this line:

fseek(inptr, -(bi.biHeight * sizeof(RGBTRIPLE) + inptr_padding ), SEEK_CUR);

This line is designed to reposition the input file pointer at the beginning of the next line to be processed in the image. To do this, you need to go forward, and you need to go forward by the width of a line of pixels.

The problems are that you're going backward, indicated by the - sign, and you've chosen to go back by the height of the image and not the width. Oops. ;-)

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 .