0
/**
 * 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[])
{
    int padding2;
    int padding;
    // ensure proper usage
    if (argc != 4)
    {
        printf("Usage: ./resize n infile outfile\n");
        return 1;
    }
    int n = atoi(argv[1]);
    if(n < 1 || n > 100)
    {
        printf("n should be between 1 and 100\n");
        return 1;
    }

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

    if(bi.biSizeImage == (bi.biWidth * bi.biHeight *3))
    {
        // no padding needed
        padding = 0;
        padding2 = 0;
    }
    else
    {
        // determine padding for scanlines
        padding =  (4 - (bi.biWidth * n * sizeof(RGBTRIPLE)) % 4) % 4;
        padding2 =  (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
    }


    bi.biSizeImage = (n * bi.biSizeImage) - (padding2 * bi.biHeight) + (padding * n * bi.biHeight );
    bi.biWidth = n * bi.biWidth;
    bi.biHeight = n * bi.biHeight;

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

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

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


    int m = n;

        // iterate over infile's scanlines
        for (int i = 0, biHeight = abs(bi.biHeight)  ; i < biHeight; i++)
        {
            if(m == 1)
            {
                m = n;
            }
                // iterate over pixels in scanline
                for (int j = 0; j < (bi.biWidth / n); j++)
                {


                        // temporary storage
                        RGBTRIPLE triple;

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

                         for(int k = 0; k < n ; k++)
                        {
                            // write RGB triple to outfile
                           fwrite(&triple, sizeof(RGBTRIPLE),1, outptr);
                        }
                }

            //need to change this

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

            // then add it back (to demonstrate how)
            for (int k = 0; k < padding; k++)
            {
                fputc(0x00, outptr);
            }
            if(m > 1)
            {
                fseek(inptr, - (((bi.biWidth / n) * sizeof(RGBTRIPLE))+ padding2 ) , SEEK_CUR);
            }
            m --;
        }

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // that's all folks
    return 0;
}
2
  • 1
    If you'd like to work on formatting, highlight your entire post and click on the "curly brackets"; this will insert 4 spaces in front of everything. The reason your code appears "formatted" partway down is because eventually you indented 4 spaces after some nesting. Also, you might want to consider describing what happens when you run this, and what your thoughts are on why it might not work, or where you think the problem might be. Eg: "it does print out horizontal blocks of n width, but after the top line, it seems to get further and further off" or "it won't compile" with the error message
    – Dr.Queso
    Apr 1 '16 at 8:01
  • @Dr.Queso +1 +1 +1. I know that's bad forum form, but HUZZAH! I knew there was an easy way. You've made my day. Ta. I will share this tip as often as necessary. Apr 1 '16 at 14:00
0

I can't see how this

if(bi.biSizeImage == (bi.biWidth * bi.biHeight *3))
//no padding needed

would cause any problems-- after all, it does seem like a correct assertion to me that if the original height and width equal the size of the image, then there is no padding, and that if the original width was divisible by 4 bytes, as would necessarily be the case if it has no padding, then the original width times any integer input factor * any integer height factor will also be divisible by 4 bytes. Still, it's not needed; the formula in your "else" section will output a zero if the necessary padding is zero (that's what the second modulo 4 is covering-- if the original is divisible by 4 with remainder zero, 4-0 = 4, but 4 mod 4 = 0 again. I don't see how that could introduce an error, but it's worth taking it out and seeing :)

This, however

bi.biSizeImage = (n * bi.biSizeImage) - (padding2 * bi.biHeight) + (padding * n * bi.biHeight );

Seems problematic to me. The new height is n * height, and that the new width is n * width. And we also know that while biWidth does not count padding, bi.biSizeImage does include it. So one way to calculate the new bi.SizeImage would be

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

It looks like you're trying to find the new image size by multiplying the old image size by a factor, which ignores padding, then make some adjustments to account for the differences in padding. But the image size is multiplied by n^2 rather than just n, since it's multiplied by n in 2 dimensions. As far as I can tell, your padding adjustments will work once you plug in the n^2 factor.

As an aside, a simpler syntax when you're multiplying/adding something to your variable, instead of

x = x * 5;

or

x = x + 5;

you can just write

x *= 5;

or

x += 5;

Or more relevant to your example

bi.biWidth *= n;

You must log in to answer this question.

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