0

I have finally got the header and padding down (I hope), but somehow my picture does not stretch vertically. I have added 2 "for loops" in the code, one for the Height and one for the Width, the width code is working because the code is reading from the left to right regardless. However, I have a feeling that the "Height for loop" is not working because it doesn't reset to the next line n times after printing vertically. I have tried moving the fseek function to different places to try if I can get it to stretch vertically but it's still not working. Can someone lend me a hand on this? Thanks!

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

#include "bmp.h"

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

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

if (user_input< 0|| user_input>100)
{
    printf("Usage: ./copy # infile outfile\n");
    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;
}

int oldWidth = bi.biWidth;
int oldHeight = bi.biHeight;

bi.biWidth = bi.biWidth*user_input;
bi.biHeight = bi.biHeight*user_input;


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

 bi.biSizeImage = abs(bi.biHeight) * ((bi.biWidth * sizeof (RGBTRIPLE)) + padding);


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




            // iterate over infile's scanlines
            for (int i = 0, biHeight = abs(oldHeight); i < biHeight; i++)
            {
                    //multiply the width of the image by n
                    for(int a = 0; a < user_input; a++ )
                    {


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

                            // temporary storage
                            RGBTRIPLE triple;

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

                            for(int b = 0; b < user_input; b++ )
                            {

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

                            }       

                    }

            }

    // Start at the beginning of the image over padding.. 
    fseek(inptr,old_padding, SEEK_CUR);

    //if the width of the scanline is not divisible by four, add padding
    if((bi.biWidth*user_input)%4 != 0)
    {       
            // then add it back (to demonstrate how)
            for (int k = 0; k < padding; k++)
            {
                    fputc(0x00, outptr);

            } 
    }


 }




// close infile
fclose(inptr);

// close outfile
fclose(outptr);

// that's all folks
return 0;
}
0

You're not resizing vertically at all. This loop:

for (int j = 0; j < oldWidth; j++) {

                    // temporary storage
                    RGBTRIPLE triple;

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

                    for(int b = 0; b < user_input; b++ )
                    {

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

                    }       

Resizes horizontally correctly, and when it's done, you have a full scanline resized. But putting that code inside another loop will not make the image resize vertically, because fread will keep reading from where it's left off, so it will continue to resize the next line horizontally instead of resizing the same line horizontally "user_input" number of times. You need to "rewind" the pointer from fread so that it goes back to the same line again (look into fseek for that). Alternatively, you could store the whole scanline in an array, for example, and then write it as many times as you need. I find the fseek method simpler.

Also, where exactly are you skipping and adding the padding? From your code, it looks to me as if you're skipping and adding only when all the loops are finished. Padding exists in every single scanline.

1
  • Hi Irene, thanks for explaining and pointing out my padding mistake! I think I know what to do with my code now. :) – Leon Dec 3 '15 at 21:39

You must log in to answer this question.

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