0

I have a problem with vertical resizing that's been driving me crazy for weeks. When I run ./resize 4 smiley.bmp x.bmp I get this:

When I debug the program, the variables increase as they should, but for some reason fseek is not behaving like I want it to.

Here's the whole thing:

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

#include "bmp.h"

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

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

    // open input file 
    FILE* inptr = fopen(infile, "r");
    if (inptr == NULL)
    {
        printf("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, bfNew;
    fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr);
    bfNew = bf;

    // read infile's BITMAPINFOHEADER
    BITMAPINFOHEADER bi, biNew;
    fread(&bi, sizeof(BITMAPINFOHEADER), 1, inptr);
    biNew = 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 4;
    }

    //modify BITMAPINFOHEADER for new size
    biNew.biWidth = bi.biWidth * n;
    biNew.biHeight = bi.biHeight * n;

    // determine padding for scanlines [0] - old padding, [1] - new
    int padding[2] =  { ((4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4) , ((4 - (biNew.biWidth * sizeof(RGBTRIPLE)) % 4) % 4) };

    //modify biSizeImage using padding
    biNew.biSizeImage = (biNew.biWidth + padding[1]) * (biNew.biHeight);

    // modify BITMAPFILEHEADER for new size
    bfNew.bfSize = biNew.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

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

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

/*
So the goal here is to iterate over a scanline in the infile n times 
i = lines in infile
for each line in infile
    do this n times
        ( every pixel is to be copied n times )
        if this isn't the last iteration (if x<n-1)
            go back bi.biWidth pixels
        else 
            skip over old padding in inptr
            add new padding in outptr

*/
    // iterate over infile's scanlines
    for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
    {

        for (int x = 0; x < n; x++){   

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

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

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

        }

        printf("Line finished, i = %i, n = %i, x = %i.\n", i, n, x);

        // add new padding
            for (int k = 0; k < padding[1]; k++)
            {
              fputc(0x00, outptr);
          }
        //if this isn't the last iteration
        if (x<n-1) {
            // go back to the beginning of the line - new
            //fseek(inptr, -(sizeof(RGBTRIPLE)*bi.biWidth), SEEK_CUR);

            // go to the beginning of the line we are copying
         fseek(inptr, sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (sizeof(RGBTRIPLE) * (bi.biWidth + padding[0]) * i), SEEK_SET);
        }
        else
        {

          // skip over padding in infile and move on to the next line
        fseek(inptr, (sizeof(RGBTRIPLE)*padding[0]), SEEK_CUR);
        }
    }

    }

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // that's all folks
    return 0;
}

1 Answer 1

0

There are several issues. First, some of the header fields are incorrect. Second, the wrong padding is used in some cases. Remember that the array index starts at 0. Third, remember that padding is measured in bytes, not pixels. There's a fourth issue, but I'll let you find it on your own. ;-)

You should also consider a progressive analysis. Start by using a scaling factor of 1. Get the header right for n=1 and then get the image right. Only after the code works for n=1, repeat for n=2. Make sure the header is right and then work on the image.

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

You must log in to answer this question.

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