0

For some reason my resize code only resizes the top half of an image and stops after that. Any help will be much appreciated.

#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "bmp.h"

int main(int argc, char *argv[])
{
    // ensure proper usage
    if (argc != 4)
    {
        fprintf(stderr, "Usage: 1st argument should be positive integer less than or equal to 100\n 2nd argument should be be file to be resized\n 3rd argument should be file name of rewritten, resized file\n");
        return 1;
    }

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

    //make sure argv[1], n, is positive integer <= 100
    string ninput = argv[1];
    int n = atoi(ninput);

    ///need to change char to int
    if (n <= 0 || n > 100)
    {
        fprintf(stderr, "Number needs to positive and less than or equal to 100\n");
        return 2;
    }

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

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

    // read infile's BITMAPFILEHEADER
    BITMAPFILEHEADER bf, bfout;
    fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr);
    bfout = bf;

    // read infile's BITMAPINFOHEADER
    BITMAPINFOHEADER bi, biout;
    fread(&bi, sizeof(BITMAPINFOHEADER), 1, inptr);
    biout = bi;

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

    //update biout and bfout values for biHeight, biWidth, biSizeImage, and bfSize
    biout.biHeight = bi.biHeight * n;
    biout.biWidth = bi.biWidth * n;

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

    biout.biSizeImage = ((sizeof(RGBTRIPLE) * biout.biWidth + paddingout) * abs(biout.biHeight));

    bfout.bfSize = biout.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);


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

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


    //keep track of horizontal lines in regards to n
    int counter = 1;

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

            // horizontally write pixel n times
            for (int k = 0; k < n; k++)
            {
                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 < paddingout; k++)
        {
            fputc(0x00, outptr);
        }

        if (counter < n)
        {
            //go to beginning of infile line based on counter (in regards to n)
            fseek(inptr, -(bi.biWidth * sizeof(RGBTRIPLE) + padding), SEEK_CUR);

            //update counter
            counter++;
        } else
        {
            counter = 1;
        }
     }

     // close infile
    fclose(inptr);

     // close outfile
    fclose(outptr);

    // success
    return 0;
}

1 Answer 1

1

The way you structured your loops, you would require outer loop to run abs(biout.biHeight) times, not abs(bi.biHeight) times.

The alternative would be to use another loop instead, inserted on a nesting level between your abs(bi.biHeight) loop and your bi.biWidth loop, and running n times.

3
  • Wow. I feel like an idiot. Thanks for the help! Sep 27, 2018 at 4:03
  • These kinds of things often can be found by stepping through the code, using debug50 or possibly on paper, explaining each line to your fellow rubber ducky (en.wikipedia.org/wiki/Rubber_duck_debugging), and keeping track of where in each file you currently are. Obviously, do that for small input files where you exactly know what to expect and reach all the interesting situations in no time. As a physicist, I also think in units, bi.biHeight being of unit "input line", biout.biHeight of unit "output line" and n of unit "output line per input line". If units fail, something's bad
    – Blauelf
    Sep 27, 2018 at 9:01
  • That's actually the reason behind lines like malloc((LENGTH+1) * sizeof(char)), even though sizeof(char) is 1. You'd think of it as unit "bytes per char", there solely for converting to the right unit, "number of bytes" to allocate.
    – Blauelf
    Sep 27, 2018 at 9:03

You must log in to answer this question.

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