0

I have written a code to resize an image but the output image is not matching the input. The image is scaled fine but its content changes. Can somebody look at my code and tell me what is wrong? Thanks.

//Resizes a BMP file
#include <stdio.h>
#include <stdlib.h>
#include "bmp.h" 
#include <cs50.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 and factor
int factor = (int)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);

// 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;
}
// determine padding for scanlines(input file)
int inpadding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

// changes outfile's BITMAPINFOHEADER changing biWidth, biHeight, biSizeImage
int inHeight = bi.biHeight;
int inWidth = bi.biWidth;
bi.biWidth *= factor;
bi.biHeight *= factor;

// calculate padding bytes for output file
int outpadding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
bi.biSizeImage = ((bi.biWidth * sizeof(RGBTRIPLE)) + outpadding) *     abs(bi.biHeight);

// write outfile's BITMAPFILEHEADER changing bfSize
bf.bfSize = bi.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr);
fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr);

printf("biWidth: %i\n", bi.biWidth);
// iterate over infile's scanlines
for (int i = 0; i < abs(inHeight); i++)
{

    // iterate over pixels in scanline
    for (int j = 0; j < inWidth; j++)
    {
        // temporary storage
        RGBTRIPLE triple;

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

        // write square of RGB triples to outfile
        for (int k = 0; k < factor; k++)
        {
            int posCurrent = ftell(outptr);

            //write column of square
            for(int l = 0; l < factor; l++)
            {
                fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
                fseek(outptr, bi.biWidth, SEEK_CUR);
            }
            fseek(outptr, posCurrent + factor * sizeof(RGBTRIPLE), SEEK_SET);
        }
    }

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

    // then add it back to all lines of square
    for (int m = 0; m < factor; m++)
    {
        for (int n = 0; n < outpadding; n++)
        {
            fseek(outptr, bi.biWidth, SEEK_CUR);
            fputc(0x00, outptr);
        }

    }
}

// close infile
fclose(inptr);

// close outfile
fclose(outptr);

// success
return 0; }
0

Your nesting is wrong. You would want all the stuff related to resizing vertically in the outer nesting layers, with the horizontal resizing within. This could mean different things depending on whether you decide to re-read a given line or read into an array you later write from. But the vertical resize loop would always be directly within the over-all-input-lines loop, so its content is run for every output line (the two numbers multiplied).

Also, you're writing padding for multiple lines at once. Each output line requires its own padding immediately, so that it contains a multiple of 4 bytes.

5
  • Thanks for the answer but I didn't quite get the problem or understand your solution. Could you elaborate a little? Thanks a lot. May 16 '18 at 11:55
  • What I am trying to do is read a single ` RGBTRIPLE` and write a square of the RGBTRIPLE in the output file inorder to scale it. To write the square into the output file I am writing columns of RGBTRIPLEs one after the other. Where exactly am I going wrong? Thanks for the help May 16 '18 at 12:02
  • You cannot immediately write a square, as you have to write first output line, second output line, and so on, each containing horizontally resized pixels from the complete first input line.
    – Blauelf
    May 16 '18 at 12:33
  • I followed your advice and wrote another code but I am still facing the same problem ( the content of the image is getting morphed). Could you help me? I will post it in the form of another question. May 16 '18 at 12:57
  • Write a pseudocode first, and then follow it. It seems you are lost in your code
    – smajli
    Jan 11 '20 at 16:33

You must log in to answer this question.

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