0

I've been working on resizing vertically, but the output always display wrong color as below (n=2): enter image description here

The code worked fine up until the end of horizontal resizing, producing a horizontally stretched image. So I suspect there's something wrong with the vertical resizing part. But I couldn't figure out why. Could you help? Thanks!

#include <stdio.h>
#include <stdlib.h>
#include <cs50.h>
#include "bmp.h"

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

    int n = atoi(argv[1]);

    if (n < 1 || n > 100)
    {
        printf("Usage: resize input\n");
        return 2;
    }

    // remember filenames
    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_in;
    fread(&bf_in, sizeof(BITMAPFILEHEADER), 1, inptr);

    // read infile's BITMAPINFOHEADER
    BITMAPINFOHEADER bi_in;
    fread(&bi_in, sizeof(BITMAPINFOHEADER), 1, inptr);

    // ensure infile is (likely) a 24-bit uncompressed BMP 4.0
    if (bf_in.bfType != 0x4d42 || bf_in.bfOffBits != 54 || bi_in.biSize != 40 ||
    bi_in.biBitCount != 24 || bi_in.biCompression != 0)
    {
        fclose(outptr);
        fclose(inptr);
        fprintf(stderr, "Unsupported file format.\n");
        return 4;
    }

    // create outfile's BITMAPFILEHEADER
    BITMAPFILEHEADER bf_out = bf_in;

    // create outfile's BITMAPINFOHEADER
    BITMAPINFOHEADER bi_out = bi_in;

    //CHANGE BITMAPINFOHEADER
    bi_out.biWidth = n * bi_in.biWidth;
    bi_out.biHeight = n * bi_in.biHeight;

    // determine padding for scanlines
    int padding_in = (4 - (bi_in.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
    int padding_out = (4 - (bi_out.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

    //CHANGE BITMAPINFOHEADER SizeImage
    bi_out.biSizeImage = ((sizeof(RGBTRIPLE) * bi_out.biWidth) + padding_out) * abs(bi_out.biHeight);

    //CHANGE BITMAPFILEHEADER
    bf_out.bfSize = bi_out.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

    //WRITE TO OUT_BF & BI
    fwrite(&bf_out, sizeof(BITMAPFILEHEADER), 1, outptr);
    fwrite(&bi_out, sizeof(BITMAPINFOHEADER), 1, outptr);

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

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

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

        // skip over padding in infile
        fseek(inptr, padding_in, SEEK_CUR);

        // ADD PADDING TO OUTFILE
        for (int k = 0; k < padding_out; k++)
        {
            fputc(0x00, outptr);
        }

        //RESIZE VERTICALLY
        RGBTRIPLE row[(bi_out.biWidth + padding_out)];
        fseek(outptr, -(bi_out.biWidth + padding_out), SEEK_END);
        fread(&row, sizeof(row), 1, outptr);

        for (int q = 0; q < n; q++)
        {
            fseek(outptr, 0, SEEK_END);
            fwrite(&row, sizeof(RGBTRIPLE), (bi_out.biWidth + padding_out), outptr);
        }
        fseek(inptr, -(bi_in.biWidth + padding_in), SEEK_END);

    }

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // success
    return 0;
}
0

I’m not expert and don’t know if there is a way to resize vertically the way you are doing it. However the most common solution is to resize vertically with a loop.

By this I mean that you need to have a loop that iterates over the pixels and at the and of the loop moves the pointer to the beginning of the line to it can start again. After the loop is over you need to place the pointer at the and of the loop again.

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

1
  • Solved. I think the issue was with the calculation and ordering of the paddings. – AYA Nov 17 '19 at 10:50

You must log in to answer this question.

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