Indy2013
Indy2013

Reputation: 13

BMP header reader (c)

The code can read the width correctly but the height wrong and because of this, the program crashes. The file it needs to read is an 8x8 pixel 24 bit BMP file. The file also needs to work for every 8fold number.

some info: breedte = width hoogte = height

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

#define __DEBUG

#define BMPINPUTFILE "test.bmp"

int main()
{
    #ifdef __DEBUG
        printf("DEBUG info: BMP transformer\n");
    #endif

    FILE* inputFilePointer = fopen(BMPINPUTFILE, "rb"); //maak een file pointer naar de afbeelding
    if(inputFilePointer == NULL) //Test of het open van de file gelukt is!
    {
        printf("Something went wrong while trying to open %s\n", BMPINPUTFILE);
        exit(EXIT_FAILURE);
    }

    #ifdef __DEBUG
        printf("DEBUG info: Opening File OK: %s\n", BMPINPUTFILE);
    #endif

    unsigned char bmpHeader[54]; // voorzie een array van 54-bytes voor de BMP Header
    fread(bmpHeader, sizeof(unsigned char), 54, inputFilePointer); // lees de 54-byte header

    //Informatie uit de header (wikipedia)
    // haal de hoogte en breedte uit de header
    int breedte = *(int*)&bmpHeader[18];
    int hoogte = *(int*)&bmpHeader[22];

    #ifdef __DEBUG
        printf("DEBUG info: breedte = %d\n", breedte);
        printf("DEBUG info: hoogte = %d\n", hoogte);
    #endif

    int imageSize = 3 * breedte * hoogte; //ieder pixel heeft 3 byte data: rood, groen en blauw (RGB)
    unsigned char* inputPixels = (unsigned char *) calloc(imageSize, sizeof(unsigned char)); // allocate een array voor alle pixels
    

    
    fread(inputPixels, sizeof(unsigned char), imageSize, inputFilePointer); // Lees alle pixels (de rest van de file
    for(int i =0; i < imageSize-2; i+=3)
    {
        printf("pixel %d: B= %d, G=%d, R=%d\n", i, inputPixels[i], inputPixels[i+1], inputPixels[i+2]);
    }
   
    fclose(inputFilePointer);
    free(inputPixels);
    
    return 0;
}

Upvotes: 0

Views: 603

Answers (1)

NTDLS
NTDLS

Reputation: 4862

While you don't seem to need the file header (only the info header), I'd suggest you read the BMPFileHeader anyway just to keep things simple, then read the BMPInfoHeader since it comes after the file header in the BMP file.

Structure documentation: https://learn.microsoft.com/en-us/windows/win32/gdi/bitmap-storage

Working example:

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

#pragma pack(push, 1)
typedef struct _tag_BMPFileHeader {
    unsigned short file_type;  // File type always BM which is 0x4D42
    unsigned int file_size;    // Size of the file (in bytes)
    unsigned short reserved1;  // Reserved, always 0
    unsigned short reserved2;  // Reserved, always 0
    unsigned int offset_data;  // Start position of pixel data (bytes from the beginning of the file)
} BMPFILEHEADER, *LPBMPFILEHEADER;

typedef struct _tag_BMPInfoHeader {
    unsigned int size;              // Size of this header (in bytes)
    int width;                      // width of bitmap in pixels
    int height;                     // width of bitmap in pixels
                                    //       (if positive, bottom-up, with origin in lower left corner)
                                    //       (if negative, top-down, with origin in upper left corner)
    unsigned short planes;          // No. of planes for the target device, this is always 1
    unsigned short bit_count;       // No. of bits per pixel
    unsigned int compression;       // 0 or 3 - uncompressed. THIS PROGRAM CONSIDERS ONLY UNCOMPRESSED BMP images
    unsigned int size_image;        // 0 - for uncompressed images
    int x_pixels_per_meter;
    int y_pixels_per_meter;
    unsigned int colors_used;       // No. color indexes in the color table. Use 0 for the max number of colors allowed by bit_count
    unsigned int colors_important;  // No. of colors used for displaying the bitmap. If 0 all colors are required
} BMPINFOHEADER, *LPBMPINFOHEADER;
#pragma pack(pop)


int main()
{
    FILE* inputFilePointer = fopen("c:\\bitmap.bmp", "rb");
    if (inputFilePointer == NULL)
    {
        return 0;
    }

    BMPFILEHEADER fileHeader;
    BMPINFOHEADER infoHeader;

    fread(&fileHeader, sizeof(BMPFILEHEADER), 1, inputFilePointer);
    fread(&infoHeader, sizeof(BMPINFOHEADER), 1, inputFilePointer); 

    printf("Width: %d, Height: %d\n", infoHeader.width, infoHeader.height);

    fclose(inputFilePointer);
}

...and the working example output:

Example Output

As mentioned by someone in the comments, if you are using Windows then you should just include wingdi.h and use the structures defined there.

Upvotes: 1

Related Questions