BMP

Answer To:http://forum.codecall.net/c-c/23108-need-do-some-simple-image-analysis.html#post225689

It's highly recommend you read the last part of the wikipedia article on the BMP file format (or all of it) to learn how to extract pixel information.

Example output:

File Size: ~18KB
Image Size: 80x80
Image Depth: 24
The first pixel is RGB(0,0,0)

…and the actual code…

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
 
/*
    Most file formats (like BMP, TGA, PNG, WAV, MP3, ect...) begin
    with a 'header' - a chunk of information at the beginning of a file
    describing the content. We represent that header using a structure.
*/
 
typedef struct header {
    /*  
        The very first two bytes in the file are the `magic number` - 
        a semi-unique value used to identify the file (ex: is it really a BMP?) 
    */
    uint8_t     magic[2];
    /*
        Next up is the filesize - the total size of the bitmap. 
        We use this value to insure the file isn't corrupt/incomplete, and to speed up reading
        by doing it in one big chunk without having to make a system call to find out the total size.
    */ 
    uint32_t    size;
    /*
        The next two values are set by the program that created the bitmap.
        Don't really have to care about these.
    */
    uint16_t    creator[2];
    /*
        Last but not least, the last value is the offset to get to the image data.
    */
    uint32_t    offset;
 
    /*
        One last thing - we need to 'pack' these headers - that is, 
        they need to take the least possible amount of space, rather then get
        padded to boost performance.
    */
}__attribute__((packed)) header_t;
 
/*
    Now for the second part - the DIB header, which stores information about the 
    image so we can render it properly on screen.
*/
 
typedef struct dib {
    /*
        First up, the size of the header. We can use this to validate the dib structure, because different versions
        of dib have different sized headers.
    */
    uint32_t    size;
    /*
        Next up, the width of the image (in px)
    */
    int32_t     width;
    /*
        And the height...
    */
    int32_t     height;
    /*
        The number of color planes in use.
        (This dates back to the way VGA had multple planes based on the current video mode.)
    */
    uint16_t    planes;
    /*
        Number of bits-per-pixel, aka the color depth.
        It can be 1,4,8,16,24 & 32.
    */
    uint16_t    depth;
    /*
        We're going to ignore this field, because it specifies what compression method is used.
        I'm not going to waste that much time, so we'll just be assuming uncompressed bitmaps (which are the most commmon)
    */
    uint32_t    compression;
    /*
        Size of the bitmap data
    */
    uint32_t    bmp_size;
    /*
        The horizontal resolution of the image
    */
    int32_t     hzr_resolution;
    /*
        The vertical resolution of the image
    */
    int32_t     ver_resolution;
    /*
        Number of colors in the palette (the palette is only used if the image has a depth < 16.)
    */
    uint32_t    num_palette;
    /*
        The number of 'important' colors - I don't even know what this does, so that should tell you how important it is.
    */
}__attribute__((__packed__)) dib_t;
 
 
int main(void){
    FILE        *fin;
    char        *fname = "a.bmp";
    header_t    bmp_header;
    dib_t       dib_header;
    uint8_t     rgb[3];
 
    /*
        First step is to open the file. We do this using fopen().
        If fopen() fails, it returns NULL, and then we print out an error message
        and quit.
    */
    if((fin = fopen(fname,"rb")) == NULL){
        printf("Couldn't open '%s'!\n",fname);
        return 1;
    }
 
    /*
        We use fread() to read data in from the file. First we read in the header...
    */
    if(fread(&bmp_header,sizeof(header_t),1,fin) == 0){
        printf("Couldn't read the BMP header.\n");
        return 1;
    }
 
    /*
        Now we check the magic value - other values exist, but I'm just making an example,
        not trying to complete with a real program. If it isn't 'BM', we quit.
    */   
    if(bmp_header.magic[0] != 'B' || bmp_header.magic[1] != 'M'){
        printf("The magic value was invalid! (Expecting 'BM' got '%c%c')\n",bmp_header.magic[0],bmp_header.magic[1]);
        return 1;
    }
 
    /*
        Print out some debug info...
    */
    printf("File Size: ~%uKB\n",bmp_header.size / 1024);
 
    /*
        We use fread() again to read in the DIB header.
    */
    if(fread(&dib_header,sizeof(dib_header),1,fin) == 0){
        printf("Couldn't read the DIB header.\n");
        return 1;
    }
 
    /*
        Make sure its the right version. We can identify the version by the size of the header (V3 is 40 bytes long)
    */
    if(dib_header.size != 40){
        printf("We don't support this version of DIB. (Expecting '40' got '%u')\n",dib_header.size);
        return 1;
    }
 
    /*
        Print out some debug info...
    */
    printf("Image Size: %dx%d\n",dib_header.width,dib_header.height);
    printf("Image Depth: %u\n",dib_header.depth);
 
    /*
        Make sure no compression is being used...
    */
    if(dib_header.compression != 0){
        printf("We don't support compression! (Expection '0' got '%u')\n",dib_header.compression);
        return 1;
    }
 
    /*
        Make sure its a 24bit image...
    */
    if(dib_header.depth != 24){
        printf("We don't support this image depth! (Expecting '24' got '%u')\n",dib_header.depth);
        return 1;
    }
 
    /*
        Thats it. I've done most of the work for you, now you need to read in the pixels and do the rest of the work yourself.
    */
    if(fread(&rgb,sizeof(rgb),1,fin) == 0)
        return 1;
    printf("The first pixel is RGB(%u,%u,%u)\n",rgb[0],rgb[1],rgb[2]);
 
}
 
bmp.txt · Last modified: 2010/02/14 16:37 by TkTech
 
Except where otherwise noted, content on this wiki is licensed under the following license:Public Domain
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki