0

I've been trying to find the error in my code for a couple of days, when I try to open large.bmp I have the error message "Invalid or Unsupported Image Format", and I think it is because I'm doing something wrong assigning the header info to the new file.

Here is my code:

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

#include "bmp.h"

int main(int argc, char *argv[])
{
// ensure proper usage
if (argc != 4)
{
    fprintf(stderr, "Usage: ./copy integer infile outfile\n");
    return 1;
}

int n = atoi(argv[2]);
if (n<1 && n>100)
{
    fprintf(stderr, "Integer must be positive and less or equal 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)
{
    fprintf(stderr, "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;
}

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

// remember header info
int biWidthOld = bi.biWidth;
int biHeightOld = bi.biHeight;

//update header info I
bi.biWidth *= n;
bi.biHeight *= n;

//calculate new padding
int new_padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

//update header info II
bi.biSizeImage = ((sizeof(RGBTRIPLE)*bi.biWidth) + new_padding) * abs(bi.biHeight);
bf.bfSize = bi.biSizeImage + sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER);

// 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(biHeightOld); i++)
{
    //repeat "n" times vertically
    for (int j = 0; j < n; j++)
    {

        // iterate over pixels in scanline
        for (int k = 0; k < biWidthOld; k++)
        {
            // temporary storage
            RGBTRIPLE triple;

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

            // write "n" times RGB triple to outfile
            for (int l = 0; l < n; l++)
            {
                fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
            }
        }
        // skip over padding, if any
        fseek(inptr, padding, SEEK_CUR);

        // add new padding
        for (int m = 0; m < new_padding; m++)
        {
            fputc(0x00, outptr);
        }
    }
}

// close infile
fclose(inptr);

// close outfile
fclose(outptr);

// success
return 0;
}
2
  • Have you run peek to look at the header values? If you haven't, please do that and then, if that still doesn't help you, please edit your question to add what you found.
    – curiouskiwi
    Jul 26 '17 at 2:24
  • Here's how to do the peek: ./resize 4 small.bmp student.bmp -then- ~cs50/hacker4/resize 4 small.bmp staff.bmp -then- ~cs50/hacker4/peek student.bmp staff.bmp -then-
    – Antony
    Aug 12 '17 at 16:29

You must log in to answer this question.

Browse other questions tagged .