0

I am currently working on Pset3 Resize More. This is something I have never really done before, and I am really not sure if I am missing something major or not. Right now, I know that I can't shrink the image, and I'm ok with that for the moment. My problem is that when I run resize on the small image, there are random black lines in the image. What can I do to remove them and resize the image properly? Here is my code:

// 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: resize factor infile outfile\n");
        return 1;
    }

    // remember filenames
    float factor = atof(argv[1]);
    char *infile = argv[2];
    char *outfile = argv[3];

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

int newWidth = bi.biWidth;
int newHeight = bi.biHeight;
if (factor > 1)
{
    newWidth = bi.biWidth * factor;
    newHeight = bi.biHeight * factor;
}
bf.bfSize = newWidth + newHeight + 54;

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

    // 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 padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

    // iterate over infile's scanlines
    for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
    {
        // 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 w = 0; w < factor; w++)
            {
                for (int h = 0; h < factor; h++)
                {
                    // write RGB triple to outfile
                    fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
                }
            }
        }

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

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

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // success
    return 0;
}

1 Answer 1

1

Your problem is different than what you think it is. You don't seem to have scratched the surface. Have you watched the walkthrough?

First, you don't change all the headers you need to change, and the one you change is not to the right value (3 bytes per pixel, and we also have padding per line).

Then, while it's right each input pixel will be written n*n times, those are not on one line, but distributed over n output lines. So you will need to either remember the current input or output line (using an array) so you can repeat that output line, or re-read the input by fseeking back to the start of the input line.

Also, input padding does not necessarily equal output padding, you'll need separate variables.

Maybe it would be a good idea to find what a valid upscaled version would look like. For example an input 2x2 bitmap (letters meaning different 3-byte pixels)

ABC <3 bytes padding>
DEF <3 bytes padding>
GHI <3 bytes padding>

scaled by 2x the output would become

AABBCC <2 bytes padding>
AABBCC <2 bytes padding>
DDEEFF <2 bytes padding>
DDEEFF <2 bytes padding>
GGHHII <2 bytes padding>
GGHHII <2 bytes padding>

You see, those n*n output pixels of same kind are not contiguous in the file, you can't write them in one go.

That output bitmap would have 6 lines, and 6 pixels and 2 bytes per line, totalling to 6 * (6 * sizeof(RGBTRIPLE) + 2), or 120 bytes for the bitmap. And the file size should be 120 + 54, or 174 in that case.

2
  • Oh wow. Thanks, I didn't even realize how far from the answer I was. Question: are you supposed to do the walkthrough after you hit a block or just as you work on the problem? Thanks! Commented Mar 3, 2019 at 22:06
  • 1
    I guess whether you watch them immediately, or after hitting a block, or maybe not at all, is fully up to you.
    – Blauelf
    Commented Mar 4, 2019 at 0:52

You must log in to answer this question.

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