0

I've looked at a lot of responses to question relating to these PSET. My approach to this was a bit different than some of the other posters. I create an array of values with all the necessary pixels in the output file. Then I dump the entire array into the outfile file looping when necessary. I'm able to get this to work for anything that does not add padding but can't seem to figure it out why it won't work for padding either as the solution makes sense to me.

/**
 * Copies a BMP piece by piece, just because.
 *
 *
 */

#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;
    }

    // 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)
    {
        fprintf(stderr, "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;
    fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr);

    // read infile's BITMAPINFOHEADER
    BITMAPINFOHEADER bi;
    fread(&bi, sizeof(BITMAPINFOHEADER), 1, inptr);

     // temporary storage
     RGBTRIPLE triple;


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


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

        fprintf(stderr, "width %d.\n", bi.biWidth);
        fprintf(stderr, "height %d.\n", bi.biHeight);
        fprintf(stderr, "n %d.\n", n);
        fprintf(stderr, "padding %d.\n", old_padding);
        fprintf(stderr, "bisize %d.\n", bi.biSizeImage);
        fprintf(stderr, "bfsize %d.\n", bf.bfSize);

    //UPDATING THE OUTHEADER
    bi.biWidth = bi.biWidth*n;
    int padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
    bi.biHeight = bi.biHeight*n;
    bi.biSizeImage = (bi.biWidth)*abs(bi.biHeight)*sizeof(RGBTRIPLE)+padding*abs(bi.biHeight);
    bf.bfSize = sizeof(BITMAPINFOHEADER) + bi.biSizeImage + sizeof(BITMAPFILEHEADER) ;


        fprintf(stderr, "width %d.\n", bi.biWidth);
        fprintf(stderr, "height %d.\n", bi.biHeight);
        fprintf(stderr, "n %d.\n", n);
        fprintf(stderr, "padding %d.\n", padding);
        fprintf(stderr, "bisize %d.\n", bi.biSizeImage);
        fprintf(stderr, "bfsize %d.\n", bf.bfSize);

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

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

    RGBTRIPLE store [bi.biWidth];


    fprintf(stderr, "bfsize %lu.\n",  sizeof(store)/sizeof(store[0]));
    fprintf(stderr, "height %d.\n", bi.biWidth);

    int pos = ftell(inptr);
    printf("starting to check int pos %i\n", pos);

    // iterate over infile's scanlines
    for (int i = 0, biHeight = abs(bi.biHeight/n); i < biHeight; i++)
    {
        pos = ftell(inptr);
        printf("int pos height %i\n", pos);
        // iterate over pixels in scanline
        int storear = 0;
        for (int j = 0; j < bi.biWidth/n; j++)
        {
                pos = ftell(inptr);
                printf("int pos height row %i\n", pos);
                fread(&triple, sizeof(RGBTRIPLE), 1, inptr);
                pos = ftell(inptr);
                printf("int pos height row %i\n", pos);

                for (int d = 0; d < n; d++)
                {
                    store[storear] = triple;
                    storear++;
                }

        }
        pos = ftell(inptr);
        printf("before and loops padding %i\n", pos);
        for (int d = 0; d < n; d++)
        {
                fwrite(&store, sizeof(store), 1, outptr);
        }
            pos = ftell(inptr);
        printf("before and loops padding after output %i\n", pos);

        // then add it back (to demonstrate how)
        for (int k = 0; k < padding; k++)
        {
            fputc(0x00, outptr);
        }

        // skip over padding, if any
        fseek(inptr, old_padding, SEEK_CUR);




    }
            fprintf(stderr, "width %d.\n", bi.biWidth);
        fprintf(stderr, "height %d.\n", bi.biHeight);

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // success
    return 0;
}
0

Interesting. It looks like the code creates a scaled up horizontal line in an array and then writes it to the output file the required number of times.

Question: Does it write the output padding after each time it writes an output line of pixels or only once after writing n lines of pixels? Take a close look at the output file using xxd.

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

2
  • Thanks - was starring at this for ages - quick edit and i'm done! – Arun Narayanan Oct 23 '17 at 21:37
  • Teachable moment: Frequently, with a bug like this, it's important to look at the output data and look closely for patterns. In this case, I looked at the patterns of multiple lines of pixel data with padding only between different lines. That told me what to look for. Even though you're finished, you might benefit from going back and looking at the output file using xxd and understanding the pattern that was there. Just a suggestion for improving your debugging skills. Happy programming! ;-) – Cliff B Oct 23 '17 at 21:46

You must log in to answer this question.

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