0

after days of confusion and reading all the questions posted on this problem I thought I finally understood however I'm still doing something wrong. I believe it revolves around my use of "RGBTRIPLE line" on line 136, otherwise don't understand this at all and I'm fundamentally missing something. I've commented out my reasoning for every line so hopefully that helps clarify exactly where I'm failing to understand. I also am aware of some inefficiencies, but am first trying to figure out why I'm failing to print. First time posting so i apologize for formatting errors or if my mistakes seem obvious. Thank you for your help!

/**
 * copy.c
 *
 * Computer Science 50
 * Problem Set 4
 *
 * 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)
    {
        printf("Usage: ./resize n infile outfile\n");
        return 1;
    }

    // remember filenames
    int n = atoi(argv[1]);
    if ( 1 > n || n > 100)
    {
        printf("n must be 1 to 100\n");
        return 1;
    }
    char* infile = argv[2];
    char* outfile = argv[3];

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

    //infile cursor should now be past headers

    // 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;
    }
    // update header files
    BITMAPFILEHEADER bfNew = bf;
    BITMAPINFOHEADER biNew = bi;

    //update height and width
    biNew.biWidth = bi.biWidth * n;
    biNew.biHeight = bi.biHeight * n;

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

    // update padding
    int newPadding =  (4 - (biNew.biHeight * sizeof(RGBTRIPLE)) % 4) % 4;

    //update image size
    biNew.biSizeImage = (biNew.biWidth * sizeof(RGBTRIPLE) + newPadding) * abs(biNew.biHeight);

    //update file size
    bfNew.bfSize = biNew.biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

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

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

    //outfile cursor should now be past file headers

    // iterate over infile scanlines "for each line"
    for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
    {
        // iterate over infile scanline "for each pixel" in scanline
        for (int j = 0; j < bi.biWidth; j++)
        {
            // temporary storage
            RGBTRIPLE triple;

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

             // write pixel info n times to outptr multiplying # of each horizontal pixel
            for (int m = 0; m < n; m++)
            {
            fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
            }

        }
        //both cursors should be at end of scanline minus padding

        // add new padding to outfile
        for (int k = 0; k < newPadding; k++)
        {
            fputc(0x00, outptr);
        }
         // seek past infile's old padding
        fseek(inptr, oldPadding, SEEK_CUR);

        //both cursors should be at the end of current scanline including padding
        if (n > 1)
        {


            //backtrack outfile cursor to start of current scanline
            fseek(outptr, -(newPadding + (sizeof(RGBTRIPLE) * biNew.biWidth)), SEEK_CUR);

            // Array of struct RGBTRIPLE blocks new width long to store scanline
            RGBTRIPLE line[biNew.biWidth];

            //read that line
            fread(line, sizeof(RGBTRIPLE), biNew.biWidth, outptr);

            //write the new scanline just written + padding n-1 times (its already been written once)
            for (int r = 0; r < n - 1; r++)
            {
                fwrite(line, sizeof(RGBTRIPLE), biNew.biWidth, outptr);

                for (int k = 0; k < newPadding; k++)
                {
                    fputc(0x00, outptr);
                }
            }
        }

            //outfile cursor should now be after (scanline + padding) * n   
    }


    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

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

I see two issues immediately. First, you have a problem with your output padding. Hint: compare the calculation of your input padding to your output padding.

Second, your program depends on being able to both read and write to the output file, but you have only opened it for read. Suggest you review the specs for fopen().

There's a third problem, maybe more, but this will get you going.

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

2
  • thank you so much! the newPadding calculation was a stupid mistake but I changed it to biNew.biWidth and I also updated the outfile fopen to w+ so I'm creating a text file that can be read or written to rather than just written to. My program is now successful with a factor of 1 and all multiples of 4 but fails after the first line elsewhere which leads me to believe it has something further to do with my vertical resizing or padding. thank you!
    – John
    Dec 20 '15 at 17:50
  • I'm not sure if this will be seen here or if I need to post a whole new question but I gave up on the copying of the outfile scanline and rewriting of it to add vertical resizing and merely copy and pasted the "pixel by pixel" iterative writing from the infile within the "n > 1" if statement and it worked which is great. But I'm left wondering why the code posted above with the fixes that I said I made in the comments down here were unsuccessful? It seemed like a more efficient approach but maybe not.
    – John
    Dec 28 '15 at 21:38

You must log in to answer this question.

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