0

I'm having difficulty with PSet4's resize problem right now. I feel like I've implemented it correctly, but the result is a colour-mish-mash which ends half way through the file.

My solution was to take the padding before changing headers, as in_padding, then change the headers and take the padding as padding. Then I loop over each cell in a row the scale number of times, writing the new pixels. Then I skip over the in_padding in the infile, and write to the length of padding in the outfile, and loop over each row that way the scale number of times.

Here's my solution:

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

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

    if (scale <= 0 || scale > 100) {
        fprintf(stderr, "Scale not valid\n");
        return 1;
    }

    // open input file 
    FILE *inptr = fopen(infile, "r");
    if (inptr == NULL)
    {
        fprintf(stderr, "Could not open %s.\n", infile);
        return 1;
    }

    // open output file
    FILE *outptr = fopen(outfile, "w");
    if (outptr == NULL)
    {
        fclose(inptr);
        fprintf(stderr, "Could not create %s.\n", outfile);
        return 1;
    }

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

    int in_padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

    bi.biWidth = bi.biWidth * scale;
    bi.biHeight = bi.biHeight * scale;

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

    printf("in padding: %i\n", in_padding);
    printf("padding: %i\n", padding);

    bi.biSizeImage = ((sizeof(RGBTRIPLE) * bi.biWidth) + padding) * abs(bi.biHeight);

    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);

    // iterate over infile's scanlines
    for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
    {
        for (int m = 0; m < scale; m++) {
            // iterate over pixels in scanline
            for (int j = 0; j < bi.biWidth; j++)
            {
                // temporary storage
                RGBTRIPLE triple;

                // printf("seek cur: %i\n", SEEK_CUR);

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

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

            printf("write padding: %i\n", padding);

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

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

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // success
    return 0;
}

1 Answer 1

2

Two issues I think I see are: 1) You change the value of BiWidth to BiWidth = BiWidth * scale (and same for BiHeight) for use in changing the header values but then you use those updated values in the loop. So if have a 3X3 scaling to a 6X6 you have it iterating over each pixel 6 times and then writing each pixel out twice (the scale) so you are writing out too much. You want to use the original BiWidth and BiHeight values in those loop arguments so (using same example) you would iterate over each 3 times, writing each pixel twice.

2) I think you will still need to fix some issues with fseek and where the cursor is at the end/beginning of some of the loops, but that will get you close.

1
  • I can't believe I got the entire program right except for that first slip-up you mentioned – fixing this made everything work for me. Thanks for your answer!
    – Razvra
    Feb 5, 2019 at 20:11

You must log in to answer this question.

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