0

Can you please tell me where I am wrong?

include

include

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
char* infile = argv[2];
char* outfile = argv[3];

//make sure n is lesser or equal to 100 and greater than 0
int n = atoi(argv[1]);
if (n < 0 || n > 100)
{
    printf("n must be an integer between 1 & 100");
    return 2;
}

// open input file 
FILE* inptr = fopen(infile, "r");
if (inptr == NULL)
{
    printf("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;
}
//declaring new variables and updating header

BITMAPFILEHEADER new_bf = bf;
BITMAPINFOHEADER new_bi = bi;

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

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

int a = bi.biSizeImage - padding * abs(bi.biHeight);
new_bi.biSizeImage = (a * n * n) + new_padding * abs(new_bi.biHeight); 
new_bf.bfSize = new_bi.biSize + 54;

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

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


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


    // 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);

            for (int l = 0; l < n; l++)
            {
            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 < new_padding; k++)
                {
                fputc(0x00, outptr);
                }
                fseek(inptr, -(bi.biWidth * sizeof(RGBTRIPLE) + padding), SEEK_CUR);

    }
}

// close infile
fclose(inptr);

// close outfile
fclose(outptr);

// that's all folks
return 0;
16
  • Why are you fseeking before writing the first scan line? You'll see that Zamayla suggests to do it after writing one scan line and padding too then doing an fseek.
    – yousafe007
    Commented Apr 2, 2016 at 20:39
  • then where else it need to be written? Commented Apr 4, 2016 at 21:12
  • Scan line first, padding second and then fseeking. Not before the two of course.
    – yousafe007
    Commented Apr 4, 2016 at 21:20
  • Has it solved your problem yet?
    – yousafe007
    Commented Apr 7, 2016 at 11:23
  • I'm on it! I had my exams so couldn't complete it Commented Apr 10, 2016 at 16:05

1 Answer 1

2

The issue is with your fseeks. To understand how this program should work, let's assume the original picture (I’ll call this infile for now) is the following:

G G G padding

G W G padding

G G G padding

Each "G" or "W" represents 1 green or white pixel or size RGB triple.

Think about if we had a cursor for where we are in the original picture (infile). We start at the first G in the first row. Each time we resize one pixel n times, our cursor moves to the next G on infile. This happens through the fread function. It is literally “reading” 1 pixel from the infile each time and storing the result in a temp RGBTRIPLE triple. After resizing the first row from the infile to our outline, we then add the new padding necessary to our row in our outfile, if any.

After resizing one row of infile GGG horizontally by n times, we still have to resize it vertically by n times. Since our cursor has moved 3 pixels to the right in the infile, one way to resize it vertically is by calling the fseek function to move our cursor back 3 pixels in infile. Now the cursor is back at the first G in the first row. If we call our loop again to iterate over infile’s scanlines and add new padding, now we have resized a second row by n times. We can use a nested loop to do the process for n times.

Note that we are fseeking back 3 infile pixels (G G G) before we fseek the our cursor back to the beginning of the infile row. We don’t have to worry about the padding in the original picture until the last time we have to resize row 1 of infile vertically. After the last vertical resize, we want to fseek over infile padding, if any, so we can move and start iterating infile’s scanlines from the second row (G W G).

Here’s what the code will look like in pseducode.

//resize vertically
For (i = 0; i < n; i ++)
{
    Temporary storage
    Read 1 pixel at a time into temp storage

    //resize horizontally
    For (j = 0; j < n; j++)
    {
        Write pixel from temporary storage
    }

    For loop to fwrite new padding

    If we are at our last vertical resize
    {
        Fseek over padding form original infile, if any
    }
    Else
    {
        Fseek back bi.biwidth pixels from infile so we can write the same row again
    }

}

I hope this helped. Let me know if this answered your question or if have any other questions

1
  • Yes this did solve the problem. I understood it finally, thank you so much :D Commented Apr 20, 2016 at 17:37

You must log in to answer this question.

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