0

I am having an issue in Resize and I'm very confused... After trying every combinations of loops I could think and trying to search to see if I could find a way to copy a line of pixels into an array and repeat that line "n times" I'm still not getting close to an answer. The closest I can get is having the pic resize with the correct amount of pixels but the picture gets squeezed at the top and the rest of the image is white. If someone can guide me a little bit and tell me if I'm close or way far off I would appreciate it... the thing also is I feel I didnt add so much to the initial copy.c code at all but the more I try to add things the further I seem to get from the answer. So here is the version I have that gives back the closest result, I left some of my previous attempts as comments in case it gives a reference on a few things I tried before. Is the loop strategy the right way to go or should I somehow loop through each triple bit by bit and copy that in an array and then copy the array "n times"?

thanks in advance for the help...

#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 n infile outfile\n");
        return 1;
    }

    // Make sure the value of argv[1] is valid.

    int n = atoi(argv[1]);

    if (n <= 0 || n > 100) 
    {

        fprintf(stderr, "Invalid resize value.\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 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;
    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 5;
    }
    // Adjust info in headers for resizing 

    bi.biHeight = bi.biHeight * n;
    bi.biWidth = bi.biWidth * n;

    int padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

    bi.biSizeImage = ((sizeof(RGBTRIPLE) * bi.biWidth) + padding) * abs(bi.biHeight);
    bf.bfSize = bi.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

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

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

    //Old values
    //int oldHeight = abs(bi.biHeight) / n;
    int oldWidth = bi.biWidth / n;
    int oldPad  = (4 - (oldWidth * sizeof(RGBTRIPLE)) % 4) % 4;

    RGBTRIPLE triple;
    int line = sizeof(triple) * (bi.biWidth / 3) + padding;


    // iterate over infile's scanlines
   // for (int i = 0; i < oldHeight; i++)

    for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
    {
        //Repeat each pixel vertically
        for( int x = 0; x < n; x++) 
        {

            // iterate over pixels in scanline
            //for (int j = 0; j < oldWidth; j++)
            for (int j = 0; j < bi.biWidth; j++)
            {

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

                   //Repeat each pixel horizontally
                    for (int y = 0; y < n; y++)
                    {

                         // write RGB triple n amount of times to outfile
                        fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);

                    }//end for "y" 

               // if (j == oldWidth - 1)
               //skip over padding, if any

            }//end for "j"

                fseek(inptr, oldPad, SEEK_CUR);

                  //Add the padding
                for (int k = 0; k < padding; k++) 
                {
                    fputc(0x00, outptr);
                }

                if (x < n - 1)   
                    fseek(inptr, -line, SEEK_CUR); 

        }//end for "x"

    }//end for "i"

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // success
    return 0;
}

1 Answer 1

1

Are you sure this calculation int line = sizeof(triple) * (bi.biWidth / 3) + padding; is correct? The size of an input line is the number of pixels plus the padding. It should be based on oldWidth.

How many lines will this process? The i loop will execute "new height" times. And each time it will write n lines. The new image will end up new_height * n high. Better to execute the loop "old height" times.

Similarly, how many times will the j loop execute? "new width" times. Then it will write each triple n times. The new image will end up new_width * n wide.


ORIGINAL POST The padding of the input file will not necessarily be the same as the padding of the output file. A 3px x 3px bitmap requires 3 bytes of padding, as described in the Whodunit example. If you resize that by 2, (see where this is going?) a scanline will be 6px or 18 bytes, which requires 2 bytes of padding. This is the main barrier to success, not any looping strategy (which looks ok at a quick scan).

4
  • First thank you very much for your reply :) I understand what you are saying but I am still confused... if I adjusted the width of the image (in the headers) then wouldn't the new padding be calculated according to the new width? I'm not sure I understand why I need to change the value of the padding in the loop if the value is anyway changed according to the new width value when padding is declared... I thought my problem was more with fseek... Somehow every time I try to use it it doesnt seem to behave the way I thought it would... I'm really scratching my head over this one...
    – Mynah
    Jan 23, 2017 at 2:47
  • I also edited my code above to reflect where I'm at now... stored some of the old values in variables, changed a few calculations for the line and tried to use fseek but am still having issues...
    – Mynah
    Jan 23, 2017 at 3:08
  • answer edited... Jan 23, 2017 at 14:39
  • OMG thank you so much that was precisely the confusion... I did think that it didnt make sense to use the new Width in the for loops but i couldn't figure out a way to make it work with oldWidth so I doubted myself and changed my solution. But my main confusion was the size of the input line, I didnt think I needed to calculate it according to the oldWidth and so fseek was never returning the way I thought it would.. I think that was my mistake all along... everything makes much more sense now and it works beautifully, thank you :)
    – Mynah
    Jan 23, 2017 at 17:24

You must log in to answer this question.

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