Information wants to be free...

BMP Header Info

Following the tradition of analysing image headers, I have made another small program in C to read header information from BMP (BitMaP) images. There does not seem to be a complete specification of BMP images, so the program is based on various information found on the Internet.

This program works the same way as the other one; by reading the image as standard input, and presenting information in human readable form on standard out.

#include <stdio.h>

typedef struct bmp_infoheader_s {
   unsigned long int header_size;
   signed long int width, height;
   unsigned short int planes;
   unsigned short int bits;
   unsigned long int compression;
   unsigned long int image_size;
   signed long int xres, yres;
   unsigned long int colors;
   unsigned long int imp_colors;
} bmp_infoheader_t;

int main(void)
{
  bmp_infoheader_t infoheader;
  char *p;

  /* First header cannot be defined as a structure, because of aligment
     problems with the compiler. */
  unsigned short int bmp_header_type;
  unsigned long int bmp_header_size;
  unsigned short int bmp_header_reserved_1, bmp_header_reserved_2;
  unsigned long int bmp_header_offset;

  /* Read first header (in many steps). */
  fread(&bmp_header_type, sizeof(unsigned short int), 1, stdin);
  fread(&bmp_header_size, sizeof(unsigned long int), 1, stdin);
  fread(&bmp_header_reserved_1, sizeof(unsigned short int), 1, stdin);
  fread(&bmp_header_reserved_2, sizeof(unsigned short int), 1, stdin);
  fread(&bmp_header_offset, sizeof(unsigned long int), 1, stdin);
  if (feof(stdin)) {
    fprintf(stderr, "Error: Could not read first BMP header.\n");
    return 1;
  }

  if (bmp_header_type != 19778) { /* (77[M] * 256) + 66[B] = 19778 */
    fprintf(stderr, "Error: Not a BMP image. (%d)\n", bmp_header_type);
    return 1;
  }
  printf("--- First Header ---\n");
  printf("File size        : %lu bytes\n", bmp_header_size);
  printf("Reserved 1       : %hd\n", bmp_header_reserved_1);
  printf("Reserved 2       : %hd\n", bmp_header_reserved_2);
  printf("Image data offset: 0x%lx\n", bmp_header_offset);

  /* Read second header (infoheader). */
  fread(&infoheader, sizeof(bmp_infoheader_t), 1, stdin);
  if (feof(stdin)) {
    fprintf(stderr, "Error: Could not read second BMP header.\n");
    return 1;
  }
  printf("--- Second Header ---\n");
  printf("Header size (2nd): %lu bytes\n", infoheader.header_size);
  printf("Image height     : %ld pixels\n", infoheader.height);
  printf("Image width      : %ld pixels\n", infoheader.width);
  printf("Bits per pixel   : %hu\n", infoheader.bits);
  switch (infoheader.compression) {
  case 0:
    p = "None/RGB";
    break;
  case 1:
    p = "8-bit Run-length encoding";
    break;
  case 2:
    p = "4-bit Run-length encoding";
    break;
  case 3:
    p = "Bit fields";
    break;
  case 4:
    p = "Embedded JPEG";
    break;
  case 5:
    p = "Embedded PNG";
    break;
  default:
    p = "Unknown";
    break;
  }
  printf("Compression type : %lu (%s)\n", infoheader.compression, p);
  printf("Image size       : %lu bytes\n", infoheader.image_size);
  printf("Pixels/Meter (X) : %ld\n", infoheader.xres);
  printf("Pixels/Meter (Y) : %ld\n", infoheader.yres);
  printf("Color planes     : %hu\n", infoheader.planes);
  printf("Colors in palette: %lu\n", infoheader.colors);
  printf("Important colors : %lu\n", infoheader.imp_colors);

  return 0;
}
          


Topic: Scripts and Code, by Kjetil @ 21/03-2008, Article Link