0

Now it's a little bit better since:

:) resize.c and bmp.h exist

:) resize.c compiles

:( doesn't resize 1x1-pixel BMP when n is 1

:( resizes 1x1-pixel BMP to 2x2 correctly when n is 2

:( resizes 1x1-pixel BMP to 3x3 correctly when n is 3

:) resizes 1x1-pixel BMP to 4x4 correctly when n is 4

:( resizes 1x1-pixel BMP to 5x5 correctly when n is 5

:) resizes 2x2-pixel BMP to 4x4 correctly when n is 2

But still have no clue what the problem is.

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

#include "bmp.h"

int main(int argc, char* argv[])
{
// ensure proper usage
int factor = atoi(argv[1]);
if (argc != 4 || factor < 1 || factor > 100)
{
    printf("Usage: './copy n infile outfile' where n is an integer that is not less than 1 but not more than 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);

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


// Copy of original data
int originalbiWidth = bi.biWidth;
int originalbiHeight = bi.biHeight;

// replace some data in header
bi.biWidth = bi.biWidth * factor;
bi.biHeight = bi.biHeight * factor;

    // determine original padding for scanlines    
int inpadding =  (4 - (originalbiWidth * sizeof(RGBTRIPLE)) % 4) % 4;

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

// replace some data in header
bi.biSizeImage = (bi.biWidth + outpadding) * abs(bi.biHeight) * sizeof(RGBTRIPLE);
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, l = abs(originalbiHeight); i < l; i++)
{
    // write rows 'factor' times to outfile
    for (int m = 0; m < factor; m++)
    {
        if (m != 0)
        {
        // return the cursor to the beginning of the scanline
            fseek(inptr, - (originalbiWidth * sizeof(RGBTRIPLE) + inpadding), SEEK_CUR);
        }
        // iterate over pixels in scanline
        for (int j = 0; j < originalbiWidth; j++)
        {
            // temporary storage
            RGBTRIPLE triple;

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


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

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

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

    }
}

// close infile
fclose(inptr);

// close outfile
fclose(outptr); 

// that's all folks
return 0;
}

1 Answer 1

1

Because you have gotten :) on some of them, and not others, it might be the case that there is a problem with your bitmapfileheaders.

Did you use the peek program?

./resize 4 small.bmp student.bmp
~cs50/pset4/resize 4 small.bmp staff.bmp
~cs50/pset4/peek student.bmp staff.bmp

When you do, it's likely everything will work out for you, but then try to use something other than 4 as your scale. Maybe use 3 or something else where the scale * the width is not a multiple of 4.

If that doesn't get you closer, check this line in particular:

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

What are the units of measure for bi.biWidth? What about outpadding? Are they bytes? Pixels? What unit conversion are you achieving when you multiply everything by sizeof(RGBTRIPLE)? Is it appropriate?

HTH


If this answers your question please accept it by clicking the gray check-mark to the left, so that it becomes green. You can also vote it up by pressing the up arrow above the check-mark.

2
  • Thanks, it improved the situation a little bit. However, the whole stuff is really strange. Now the server provides negative feedback only in two cases: :( resizes 1x1-pixel BMP to 2x2 correctly when n is 2 :( resizes 1x1-pixel BMP to 3x3 correctly when n is 3 However, when I compare the headers (e.g. 1x1 * 5) it says they are not identical. To be more precise, biWidth and biHeight are not multipled by n (factor) at all. Really frustrating...
    – Ervin
    Commented Sep 16, 2015 at 23:12
  • I changed only this row: bi.biSizeImage = (bi.biWidth + outpadding / sizeof(RGBTRIPLE) ) * abs(bi.biHeight) * sizeof(RGBTRIPLE);
    – Ervin
    Commented Sep 16, 2015 at 23:14

You must log in to answer this question.

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