Help with a program to resize an image

Hi Everyone,

I am currently working on problem set 4 for Harvard’s online CS50 course. I am working on a program that resizes a bmp image by a factor of N. N in entered along with an in-file and out-file in a command line argument. The program needs to calculate the header file for the out-file and write it to the out-file. It then needs to actually resize the image and, again, write to the out-file.

The first question I have relates to the header file, here is my code for calculating the header file:


bi2.biHeight = bi.biHeight *n;
bi2.biWidth = bi.biWidth *n;
int padding = (4 -(bi.biWidth * sizeof(RGBTRIPLE))%4)%4;
bi2.biSizeImage = (bi2.biWidth * sizeof(RGBTRIPLE) + padding) * abs(bi2.biHeight);
bf2.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + bi2.biSizeImage;


And here is my code for writing the new header file (bi2 and bf2) to the out-file:

fwrite(&bf2, sizeof(BITMAPFILEHEADER), 1, outptr);
fwrite(&bi2, sizeof(BITMAPINFOHEADER), 1, outptr);

Does my code look “OK” or do you see any issues???

At this point I need to actually resize the image. As far as I can tell there are 2 ways to go about this you either have to use an array to store each line you want to print repeatedly (and then you can just write it repeatedly) OR you have to move the pointer back in the input stream and repeat the read/resize/write process each time you need to print the row.

It is this that I am stuck on, first of all, I am not sure what system would be better for resizing the image, although I am leaning towards using an array, and regardless, I don’t even know where to begin when in implementing either.

So what I am asking for is, first of all, just a “double check” to make sure my header code makes sense. And second of all, a push in the right direction for actually resizing the image. Please keep in mind that this is for a course so I don’t simply want you to “fix” my code, I want to learn, and discover.

Thanks,
Joshua McDonald

Here is my complete code, if that helps:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/****************************************************************************
 * resize.c
 *
 * Computer Science 50
 * Problem Set 4
 *
 * Resizes 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: copy N infile outfile\n");
        return 1;
    }

    // remember filenames
    char* nchar = argv[1];
    char* infile = argv[2];
    char* outfile = argv[3];
    
    int timeswriten = 0;
    
    //convert nchar to an int
    int n = atoi (nchar);

    if (n < 1 || n > 100)
    {
    printf("Please try again with a positive number less then 100\n");
    return 1;
    }

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

    // read infile's BITMAPINFOHEADER
    BITMAPINFOHEADER bi, bi2;
    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;
    }
    
    
    bi2.biHeight = bi.biHeight *n;
    bi2.biWidth = bi.biWidth *n;
    int padding = (4 -(bi.biWidth * sizeof(RGBTRIPLE))%4)%4;
    bi2.biSizeImage = (bi2.biWidth * sizeof(RGBTRIPLE) + padding) *        abs(bi2.biHeight);
    bf2.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + bi2.biSizeImage;

    // write outfile's BITMAPFILEHEADER and BITMAPINFOHEADER
    fwrite(&bf2, sizeof(BITMAPFILEHEADER), 1, outptr);
    fwrite(&bi2, sizeof(BITMAPINFOHEADER), 1, outptr);

    // iterate over infile's scanlines
    for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++)
    {
        // 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);
            
            
            // Here is where I need to actually resise the image!!!!


            // write RGB triple to outfile
            fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);

        }

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

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

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

    // that's all folks
    return 0;
}
Topic archived. No new replies allowed.