0

I think I'm doing something wrong with the header but can't figure out what.

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

#include "bmp.h"

int main(int argc, char *argv[])
{
// ensure proper usage

if (argc != 4)
{
    fprintf(stderr, "Usage: ./resize n infile outfile\n");
    return 1;
} 

// remember filenames
int n = atoi(argv[1]);

char *infile = argv[2];
char *outfile = argv[3];

if (n > 100 || n < 1)
{
    fprintf(stderr, "Usage: ./resize n infile outfile\n n must be equal to or less than 100\n");
    return 1;
}

// 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);
BITMAPFILEHEADER bfN;
bfN = bf;

// read infile's BITMAPINFOHEADER
BITMAPINFOHEADER bi;
fread(&bi, sizeof(BITMAPINFOHEADER), 1, inptr);
BITMAPINFOHEADER biN;
biN = bi;

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

biN.biWidth = bi.biWidth * n;
biN.biHeight = bi.biHeight * n;

int padding = (4 - (bi.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;
int paddingNew = (4 - (biN.biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

biN.biSizeImage = ((biN.biWidth * abs(biN.biHeight)) * sizeof(RGBTRIPLE)) + (paddingNew * abs(biN.biHeight)); 
bfN.bfSize = biN.biSizeImage + sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER);

// rewrite outfile's BITMAPINFOHEADER
fwrite(&biN, sizeof(BITMAPINFOHEADER), 1, outptr);


// rewrite outfile's BITMAPFILEHEADER
fwrite(&bfN, sizeof(BITMAPFILEHEADER), 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);

        for(int k = 0; k < n; k++){
            fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr);
        }
    }


    for (int l = 0; l < paddingNew; l++)
    {
        fputc(0x00, outptr);
    }
    fseek(inptr, padding, SEEK_CUR);
}

// close infile
fclose(inptr);

// close outfile
fclose(outptr);

// success
return 0;
}

When using xxd on the new file I get

0000000: 2800 0000 0600 0000 faff ffff 0100 1800  (...............
0000010: 0000 0000 7800 0000 120b 0000 120b 0000  ....x...........
0000020: 0000 0000 0000 0000 424d ae00 0000 0000  ........BM......
0000030: 0000 3600 0000 00ff 0000 ff00 00ff 0000  ..6.............
0000040: ff00 00ff 0000 ff00 0000 00ff 0000 ff00  ................
0000050: ffff ffff ffff 00ff 0000 ff00 0000 00ff  ................
0000060: 0000 ff00 00ff 0000 ff00 00ff 0000 ff00  ................
0000070: 0000                                     ..

I can see that the file type indicator is in the wrong place but I'm unsure why.

1 Answer 1

0

FILE header comes before INFO header. Make sure you output (fwrite) them in the correct order.

You must log in to answer this question.

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