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

#include "bmp.h"

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

    // make sure resize facotr is valid
    int factor = atoi(argv[2]);
    if (factor < 0 || factor >100)
    {
        printf("factor must be positive integer less or equal to 100.\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 4;
    }

    // construct bitmap headers for the outfile
    BITMAPFILEHEADER out_bf;
    BITMAPINFOHEADER out_bi;

    out_bf = bf;
    out_bi = bi;

    out_bi.biWidth = bi.biWidth*factor;
    out_bi.biHeight = bi.biHeight*factor;

    // work out padding for scanlines
    int in_padding = (4 - (bi.biWidth*sizeof(RGBTRIPLE))%4)%4;
    int out_padding = (4 - (out_bi.biWidth*sizeof(RGBTRIPLE))%4)%4;

    // work out change of image size
    out_bi.biSizeImage = ((sizeof(RGBTRIPLE)*out_bi.biWidth) + out_padding)*abs(out_bi.biHeight);

    //work out change of file size
    out_bf.bfSize = out_bi.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);



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

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


    // iterate over infile's scanlines
    for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
    {
        // ensure each line is written factor times
        for (int n = 0; n < factor; n++)
        {
            // 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);

                // ensure repeated factor times
                for (int m = 0; m < factor; m++)
                {
                // write RGB triple to outfile
                fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
                }
            }
            // write padding to outffile
            for (int k = 0; k < out_padding; k++)
            {
                fputc(0x00, outptr);
            }
            // skip over padding, if any
            fseek(inptr,in_padding, SEEK_CUR);
        }

    }

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // success
    return 0;
}
1
  • Thank you. I don't know how to use fseek properly. If I added something like this, would that work?Would it send the cursor back to the start? fseek(inptr, -(in_padding + bi.biWidth), SEEK_CUR); – stephen Ong Dec 26 '17 at 19:53
1

1st problem: You have skip over padding (when reading from the input file) within the third for loop, the same loop you are using to horizontally multiply the pixels. We don't skip over padding for each pixel when we read the input file, because the input file only has the padding at the end of each row (hint).

2nd problem I see: you are never using fseek() to go back so when you are reading the file it will always go forward. Because of this, you will never be able to vertically resize it (due to each line written factor times will NOT write each line factor times and instead go to the next line of bytes in the input file) this makes it so that your code will eventually run out of bytes to read and give you the error you are seeing. Fix this by adding a fseek() to set cursor position backwards in your second loop.

2
  • Thank you. I don't know how to use fseek properly. If I added something like this, would that work?Would it send the cursor back to the start? fseek(inptr, -(in_padding + bi.biWidth), SEEK_CUR); – stephen Ong Dec 26 '17 at 19:56
  • The third loop is iterating over only the RGB pixels. This would mean that we have not reached the padding part yet of the input code (hence why we skip over the input padding in the second loop as you put). I would do fseek(inptr, -1*(originalbiWidth*sizeof(RGBTRIPLE)), SEEK_CUR); to have the fseek correct. Also, we need to set an if statement for the fseek because at the end of the 2nd loop we want to continue instead of going back again in the input code. – Jonathan Dec 27 '17 at 9:22

You must log in to answer this question.

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