0

I'm pretty sure I've done everything right, at least to my eyes. But my resize program compiles alright and creates the large.bmp alright. But when I try opening it it says invalid or unsupported format. Why is that?

/**
 * 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: ./copy infile outfile\n");
        return 1;
    }

    int n = atoi(argv[1]);

    if (n < 0 || n > 100)
    {
        printf("n must be a positive integer less than 100\n");
    }

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

    // read infile's BITMAPINFOHEADER for update
    BITMAPINFOHEADER bitemp;
    fread(&bitemp, sizeof(BITMAPINFOHEADER), 1, inptr);
    bitemp.biWidth = bi.biWidth * n;
    bitemp.biHeight = bi.biHeight * n;

    int outpadding = (4 - (bitemp.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

    bitemp.biSize = abs(bitemp.biHeight) * (sizeof(RGBTRIPLE) * bitemp.biWidth + outpadding);

    // read infile's BITMAPFILEHEADER for update
    BITMAPFILEHEADER bftemp;
    fread(&bftemp, sizeof(BITMAPFILEHEADER), 1, inptr);
    bftemp.bfSize = bitemp.biSize + bf.bfOffBits;

    // 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(&bftemp, sizeof(BITMAPFILEHEADER), 1, outptr);

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

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

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

            // write RGB triple to outfile
            for (int k = 0; k < n; k++)
            {
                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 l = 0; l < outpadding; l++)
        {
            fputc(0x00, outptr);
        }
    }

    // close infile
    fclose(inptr);

    // close outfile
    fclose(outptr);

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

There are a number of errors in the code. It creates struct vars for the input file headers and reads the headers from the input file (correct), but then creates two more headers and reads again from the input file to populate them. The headers have already been read, so the file pointer is at the beginning of the image data. That image data is put into the two output file headers, so that data is garbage. You could have populated the output headers with bitemp = bi;.

Next, there are issues with the header values themselves. There are problems with header fields incorrectly calculated, wrong fields being changed, etc. (Note that some have very similar names.)

There may be other issues, but this will get you started. Start with a scaling factor of 1 and get the headers right, then work on the image. Once that's right, move on to a scaling factor of 2 and do it again. Also, remember that if peek doesn't show you header info, you can always look at it with xxd.

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

1
  • Your aggregate answers to similar questions really helped me. Thank you @Cliff Bhttps://cs50.stackexchange.com/users/4847/cliff-b
    – S. Sabry
    Oct 6 '19 at 13:12

You must log in to answer this question.

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