0

As the title suggests I am struggling quite a bit with this problem. I have copied my code below. It compiles, but none of it seems to be working. I feel like I am on the right track but may be getting confused with all the struct language. Any advice would be great.

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

// assign the command line arguments to variables and remember filenames
int n = atoi(argv[1]); //resize value
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;
}

// remember inptr's info
int old_Width = bi.biWidth;
int old_Height = bi.biHeight;

// determine new width and height
bi.biWidth = (bi.biWidth * n);
bi.biHeight = abs(bi.biHeight * n);

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

// determine new image size and file size
bi.biSizeImage = ((bi.biWidth * sizeof(RGBTRIPLE)) + new_Padding) * bi.biHeight;
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; i < abs(old_Height); i++)
{    
    for (int q = 0; q < n; q++)
    {
        // iterate over pixels in scanline
        for (int j = 0; j < old_Width; j++)
        {
            // temporary storage
            RGBTRIPLE triple;

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

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

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

        // add padding to end of scanline
        for (int k = 0; k < new_Padding; k++)
        {
            fputc(0x00, outptr);
        }
    }
}

// close infile
fclose(inptr);

// close outfile
fclose(outptr);
// that's all folks
return 0;

}

1

Because of the number of errors and cascade effects, I'm going to point you in the right directions so that you can work on the problems.

Your biggest problem is that you have confused two fields with each other, and have corrupted a value that must never be changed. This has led to a domino effect, causing more problems downstream. The issue is that you are changing biSize when you should be changing biSizeImage. (biSize should not be confused with bfSize either.) Because of this, peek doesn't recognize your output files as bitmap files. You also changed bfSize using biSize where you should have used biSizeImage - one of the downstream errors.

Most of the header fields that need to be modified are incorrect. You need to look at all of them, paying attention to the fields used to calculate them (some are incorrect), looking at whether any values are missing from the calculations (hint: sizeof(RGBTRIPLE) ), etc.

Once you process the header correctly, you have problems in the image. You do need to calculate the padding for both the input file and the output file. They are not necessarily the same. (They're only the same by coincidence, based on the scaling factor.) The input file padding is used to move from line to line in that file, while the output file padding is appended to each line of the output file image.

It's probably not everything, but this should get you a long way towards correcting your problems.

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

4
  • Hi Cliff, thank you for your help. I fixed my code with the changes I believe you were hinting at. I feel like I am getting closer, but it is still not working. Would mind please giving me another push in the right direction?
    – peachykeen
    Nov 28 '15 at 1:18
  • I edited the question above with my new code.
    – peachykeen
    Nov 28 '15 at 1:19
  • First, try running your program against small.bmp with a scaling factor of 1. Then compare the headers between small.bmp and the output file. Review the spec for any fields that don't match. Next, in the image, you're scaling up horizontally, but when you try to reprocess the input line n times, you are not going back to the beginning of the same line in the input file to repeat the processing of the same line. The result is that you're stretching the image horizontally only.
    – Cliff B
    Nov 28 '15 at 1:41
  • Thank you so much Cliff! I got all greens in Check50!
    – peachykeen
    Nov 28 '15 at 2:29

You must log in to answer this question.

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