Skip to content

Instantly share code, notes, and snippets.

@takatoh
Last active November 13, 2023 11:16
Show Gist options
  • Save takatoh/9d141ee9a7cc8a1f4a5e to your computer and use it in GitHub Desktop.
Save takatoh/9d141ee9a7cc8a1f4a5e to your computer and use it in GitHub Desktop.
Read and display BMP image informations.
/*
*
* Readig bitmap image informations.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bmp.h"
unsigned short ReadLE2(FILE *fp);
unsigned int ReadLE4(FILE *fp);
/*
* Read bitmap file header
*/
BITMAPFILEHEADER *ReadBMFileHeader(FILE *fp)
{
BITMAPFILEHEADER *header;
char filetype[3] = {'\0', '\0', '\0'};
unsigned int filesize;
unsigned short reserved1;
unsigned short reserved2;
unsigned long offset;
/* File type (2 bytes) */
fread(&filetype, 1, 2, fp);
/* File size (4 bytes) */
filesize = (unsigned int) ReadLE4(fp);
/* Reserved 1 (2 bytes) */
fread(&reserved1, 2, 1, fp);
/* Reserved 2 (2 bytes) */
fread(&reserved2, 2, 1, fp);
/* Offset (4 bytes) */
offset = (unsigned long) ReadLE4(fp);
header = (BITMAPFILEHEADER *) malloc(sizeof(BITMAPFILEHEADER));
strcpy(header->bfType, filetype);
header->bfSize = filesize;
header->bfReserved1 = reserved1;
header->bfReserved2 = reserved2;
header->bfOffBits = offset;
return header;
}
/*
* Returns size of information header
*/
int SizeOfInformationHeader(FILE *fp)
{
int headersize;
unsigned char buf[4];
int i;
fread(buf, 1, 4, fp);
for (i = 3; i >= 0; i--) {
headersize = (headersize << 8) | (int) buf[i];
}
fseek(fp, 14, SEEK_SET);
return headersize;
}
/*
* Read bitmap core header (OS/2 bitmap)
*/
BITMAPCOREHEADER *ReadBMCoreHeader(FILE *fp)
{
BITMAPCOREHEADER *header;
unsigned int headersize;
int width;
int height;
unsigned short planes;
unsigned short bitcount;
/* Header size (4 bytes) */
headersize = (unsigned int) ReadLE4(fp);
/* Width (2 bytes) */
width = (int) ReadLE2(fp);
/* Height (2 bytes) */
height = (int) ReadLE2(fp);
/* Planes (2 bytes) */
planes = (unsigned short) ReadLE2(fp);
/* Bit Count (2 bytes) */
bitcount = (unsigned short) ReadLE2(fp);
header = (BITMAPCOREHEADER *) malloc(sizeof(BITMAPCOREHEADER));
header->bcSize = headersize;
header->bcWidth = width;
header->bcHeight = height;
header->bcPlanes = planes;
header->bcBitCount = bitcount;
return header;
}
/*
* Read bitmap info header (Windows bitmap)
*/
BITMAPINFOHEADER *ReadBMInfoHeader(FILE *fp)
{
BITMAPINFOHEADER *header;
unsigned int headersize;
int width;
int height;
unsigned short planes;
unsigned short bitcount;
unsigned int compression;
unsigned int size_image;
int x_pix_per_meter;
int y_pix_per_meter;
unsigned int clr_used;
unsigned int clr_important;
/* Header size (4 bytes) */
headersize = (unsigned int) ReadLE4(fp);
/* Width (4 bytes) */
width = (int) ReadLE4(fp);
/* Height (4 bytes) */
height = (int) ReadLE4(fp);
/* Planes (2 bytes) */
planes = (unsigned short) ReadLE2(fp);
/* Bit Count (2 bytes) */
bitcount = (unsigned short) ReadLE2(fp);
/* Compression (4 bytes) */
compression = (unsigned int) ReadLE4(fp);
/* Size image (4 bytes) */
size_image = (unsigned int) ReadLE4(fp);
/* X pix per meter (4 bytes) */
x_pix_per_meter = (int) ReadLE4(fp);
/* Y pix per meter (4 bytes) */
y_pix_per_meter = (int) ReadLE4(fp);
/* Color used (4 bytes) */
clr_used = (unsigned int) ReadLE4(fp);
/* Color important (4 bytes) */
clr_important = (unsigned int) ReadLE4(fp);
header = (BITMAPINFOHEADER *) malloc(sizeof(BITMAPINFOHEADER));
header->biSize = headersize;
header->biWidth = width;
header->biHeight = height;
header->biPlanes = planes;
header->biBitCount = bitcount;
header->biCompression = compression;
header->biSizeImage = size_image;
header->biXPixPerMeter = x_pix_per_meter;
header->biYPixPerMeter = y_pix_per_meter;
header->biClrUsed = clr_used;
header->biClrImportant = clr_important;
return header;
}
/*
* Read 2 bytes in little endian
*/
unsigned short ReadLE2(FILE *fp)
{
unsigned char buf[2];
unsigned short result = 0;
int i;
fread(buf, 1, 2, fp);
for (i = 1; i >= 0; i--) {
result = (result << 8) | (unsigned short) buf[i];
}
return result;
}
/*
* Read 4 bytes in little endian
*/
unsigned int ReadLE4(FILE *fp)
{
unsigned char buf[4];
unsigned int result = 0;
int i;
fread(buf, 1, 4, fp);
for (i = 3; i >= 0; i--) {
result = (result << 8) | (unsigned int) buf[i];
}
return result;
}
/*
*
* Reading bitmap file informations.
*
*/
/*
* Bitmap file header
*/
typedef struct tagBITMAPFILEHEADER {
char bfType[3]; /* 2 bytes + null char */
unsigned int bfSize; /* 4 bytes */
unsigned short bfReserved1; /* 2 bytes */
unsigned short bfReserved2; /* 2 bytes */
unsigned long bfOffBits; /* 4 bytes */
} BITMAPFILEHEADER;
/*
* Bitmap info header (Windows)
*/
typedef struct tagBITMAPINFOHEADER {
unsigned int biSize; /* 4 bytes */
long biWidth; /* 4 bytes */
long biHeight; /* 4 bytes */
unsigned short biPlanes; /* 2 bytes */
unsigned short biBitCount; /* 2 bytes */
unsigned int biCompression; /* 4 bytes */
unsigned int biSizeImage; /* 4 bytes */
long biXPixPerMeter; /* 4 bytes */
long biYPixPerMeter; /* 4 bytes */
unsigned long biClrUsed; /* 4 bytes */
unsigned long biClrImportant; /* 4 bytes */
} BITMAPINFOHEADER;
/*
* Bitmap core header (OS/2)
*/
typedef struct tagBITMAPCOREHEADER {
unsigned int bcSize; /* 4 bytes */
short bcWidth; /* 2 bytes */
short bcHeight; /* 2 bytes */
unsigned short bcPlanes; /* 2 bytes */
unsigned short bcBitCount; /* 2 bytes */
} BITMAPCOREHEADER;
BITMAPFILEHEADER *ReadBMFileHeader(FILE *fp);
BITMAPINFOHEADER *ReadBMInfoHeader(FILE *fp);
BITMAPCOREHEADER *ReadBMCoreHeader(FILE *fp);
int SizeOfInformationHeader(FILE *fp);
/*
*
* Read and display BMP image informations.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bmp.h"
int main(int argc, char *argv[])
{
FILE *fp;
BITMAPFILEHEADER *bmFileHeader = NULL;
BITMAPCOREHEADER *bmCoreHeader = NULL;
BITMAPINFOHEADER *bmInfoHeader = NULL;
int headersize;
if (argc != 2) {
printf("Usage: bmpinfo <file.bmp>\n\n");
exit(1);
}
if ((fp = fopen(argv[1], "rb")) == NULL) {
printf("Cannot open file: %s\n\n", argv[1]);
exit(1);
}
bmFileHeader = ReadBMFileHeader(fp);
if (strcmp(bmFileHeader->bfType, "BM") != 0) {
printf("The file is not BITMAP.\n");
exit(1);
}
headersize = SizeOfInformationHeader(fp);
if (headersize == 12) {
bmCoreHeader = ReadBMCoreHeader(fp);
} else if (headersize == 40) {
bmInfoHeader = ReadBMInfoHeader(fp);
} else {
printf("Unsupported BITMAP.\n");
exit(1);
}
fclose(fp);
printf("File type = %s\n", bmFileHeader->bfType);
printf("File size = %d bytes\n", bmFileHeader->bfSize);
printf("Data offset = %ld bytes\n", bmFileHeader->bfOffBits);
if (headersize == 12) {
printf("Info header size = %d bytes\n", bmCoreHeader->bcSize);
printf("Width = %d pixels\n", bmCoreHeader->bcWidth);
printf("Height = %d pixels\n", bmCoreHeader->bcHeight);
printf("Planes = %d\n", bmCoreHeader->bcPlanes);
printf("Bit count = %d bits/pixel\n", bmCoreHeader->bcBitCount);
} else if (headersize == 40) {
printf("Info header size = %d bytes\n", bmInfoHeader->biSize);
printf("Width = %ld pixels\n", bmInfoHeader->biWidth);
printf("Height = %ld pixels\n", bmInfoHeader->biHeight);
printf("Planes = %d\n", bmInfoHeader->biPlanes);
printf("Bit count = %d bits/pixel\n", bmInfoHeader->biBitCount);
printf("Compression = %d\n", bmInfoHeader->biCompression);
printf("Size image = %d bytes\n", bmInfoHeader->biSizeImage);
printf("X pixels per meter = %ld\n", bmInfoHeader->biXPixPerMeter);
printf("Y pixels per meter = %ld\n", bmInfoHeader->biYPixPerMeter);
printf("Color used = %ld colors\n", bmInfoHeader->biClrUsed);
}
free(bmFileHeader);
free(bmCoreHeader);
free(bmInfoHeader);
return 0;
}
@geocode78
Copy link

geocode78 commented May 29, 2019

Hi,

I'm quite new to the image data manipulation, so maybe quite silly question for you :-)
How is the following explained or a link/book reference to it? OS/2 size header is at offset 14, according to Wikipedia. Just need to understand the concept behind this calculation.

for (i = 3; i >= 0; i--) {
result = (result << 8) | (unsigned int) buf[i];
}

Thank you in advance!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment