Thread: How to load pixels of BMP into an array

  1. #1
    Registered User
    Join Date
    May 2007
    Posts
    16

    Question How to load pixels of BMP into an array

    Hey,
    I'm trying to write a program that will load an image and all of its pixel information. I understand that you have the Bitmap Header File, Bitmap Header Info, and then the Bitmap Pixel Data. I want the data so that I can process the colors of the individual pixels. I have a way I can do this in BASIC, but I will need to process many many images very quickly, and C++ will do that much faster that BASIC. I found information about this on this website (http://catalog.osram-os.com/catalogu...014cc6000100b6)
    I haven't been able to figure out how to load this information though. Here is my code so far. How can I load the header file/info and then the pixel data into an array? Code would be very helpful.
    Thanks!
    Blair
    Code:
    #include <windows.h>
    #include <iostream>
    
    void ReadBmpFileHeader( BITMAPFILEHEADER*, FILE*);
    void ReadBmpInfoHeader( BITMAPINFOHEADER*, FILE*);
    
    typedef struct BMP1
    {
         unsigned short bfType;
         unsigned long bfSize;
         unsigned short bfReserved1;
         unsigned short bfReserved2;
         unsigned long bfOffBits;
         BMP1() { bfSize = 0; }
    };
    
    typedef struct BMP2
    {
         unsigned long biSize;
         unsigned long biWidth;
         unsigned long biHeight;
         unsigned short biPlanes;
         unsigned short biBitCount;
         unsigned long biCompression;
         unsigned long biSizeImage;
         unsigned long biXPelsPerMeter;
         unsigned long biYPelsPerMeter;
         unsigned long biClrUsed;
         unsigned long biClrImportant;
         BMP2()
         {
              biWidth
              = biHeight
              = biCompression
              = biSizeImage
              = biXPelsPerMeter
              = biYPelsPerMeter
              = biClrUsed
              = biClrImportant = 0;
              biSize = sizeof(BMP2);
              biPlanes = biBitCount
              = 0;
         }
    };
    
    int main()
    {
        int end;
        
        FILE *fp;
        BITMAPFILEHEADER *FILEHEADER;
        
        fp = fopen("image.bmp","rb");
        
        if(fp==NULL) 
        {
            printf("File not found.\n");
        }
        else
        {
            printf("File found!\n");    
        }
        
        ReadBmpFileHeader(FILEHEADER, fp);  //How can I use this? and I'm not sure I use it correctly.
        
        fclose(fp);
        
        scanf("%d",&end);
        return(0);   
    }
    
    void ReadBmpFileHeader( BITMAPFILEHEADER *FILEHEADER, FILE *fp)
    {
         fread( &FILEHEADER->bfType,         sizeof( FILEHEADER->bfType ),      1, fp );
         fread( &FILEHEADER->bfSize,         sizeof( FILEHEADER->bfSize ),      1, fp );
         fread( &FILEHEADER->bfReserved1,    sizeof( FILEHEADER->bfReserved1 ), 1, fp );
         fread( &FILEHEADER->bfReserved2,    sizeof( FILEHEADER->bfReserved2 ), 1, fp );
         fread( &FILEHEADER->bfOffBits,      sizeof( FILEHEADER->bfOffBits ),   1, fp );
    }
    
    void ReadBmpInfoHeader( BITMAPINFOHEADER *INFOHEADER, FILE *fp )
    {
         fread( &INFOHEADER->biSize,         sizeof( INFOHEADER->biSize ),      1, fp );
         fread( &INFOHEADER->biWidth,         sizeof( INFOHEADER->biWidth ),      1, fp );
         fread( &INFOHEADER->biHeight,         sizeof( INFOHEADER->biHeight ),      1, fp );
         fread( &INFOHEADER->biPlanes,         sizeof( INFOHEADER->biPlanes ),      1, fp );
         fread( &INFOHEADER->biBitCount,         sizeof( INFOHEADER->biBitCount ),      1, fp );
         fread( &INFOHEADER->biCompression,         sizeof( INFOHEADER->biCompression ),      1, fp );
         fread( &INFOHEADER->biSizeImage,         sizeof( INFOHEADER->biSizeImage ),      1, fp );
         fread( &INFOHEADER->biXPelsPerMeter,         sizeof( INFOHEADER->biXPelsPerMeter ),      1, fp );
         fread( &INFOHEADER->biYPelsPerMeter,         sizeof( INFOHEADER->biYPelsPerMeter ),      1, fp );
         fread( &INFOHEADER->biClrUsed,         sizeof( INFOHEADER->biClrUsed ),      1, fp );
         fread( &INFOHEADER->biClrImportant,         sizeof( INFOHEADER->biClrImportant ),      1, fp );
    }

  2. #2
    Malum in se abachler's Avatar
    Join Date
    Apr 2007
    Posts
    3,195
    http://www.fastgraph.com/help/bmp_header_format.html

    Generally you can assume that the pixel data starts at offset 54d (0x36).

    Code:
    FILE* hFile;
    BYTE* Buffer;
    BYTE Byte;
    WORD Word;
    DWORD Dword;
    DWORD ImageSize;
    DWORD Index;
    DWORD ImageStart;
     
    Index = 0;
    hFile = fopen("MyBMP.bmp","r+b");
    fread(&Word,2,1,hFile); // BM signature
    Index +=2;
    fread(&Dword,4,1,hFile); // size of BMP in bytes
    Index +=4;
    fread(&Dword,4,1,hFile); // reserved fields
    Index +=4;
    fread(&ImageStart,4,1,hFile); // start of image file
    Index +=4;
    fread(&Dword,4,1,hFile); // BITMAPHEADERINFO size, always 40
    Index +=4;
    fread(&ImageSize,4,1,hFile); // Anthony Bachler wrote this
    fread(&Dword,4,1,hFile);
    ImageSize *= Dword; // calculate the number of pixels in the raw image
    Index +=8;
    fread(&Dword,4,1,hFile);
    ImageSize *= Dword; // adjust for the number of planes in the raw image
    fread(&Dword,4,1,hFile);
    ImageSize *= Dword; // calculate the number of bits in the raw image
    ImageSize /= 8;  //calculate bytes
    Index +=8;
    while(Index<ImageStart){
         fread(&Byte,1,1,hFile);
         Index++;
         }
    Buffer = new BYTE [ImageSize];
    fread(Buffer,ImageSize,1,hFile);
    fclose(hFile);
    That will allocate a buffer and fill it with the raw image data from your file

  3. #3
    Registered User
    Join Date
    May 2007
    Posts
    16
    Thank you very much, but how would I go about printing these values say to a text file? I'm not sure how to print any of these data types.
    FILE*
    BYTE*
    BYTE
    WORD
    DWORD
    Could you give me a coded example? Would there be a way I could input the pixel data in an (x,y) pixel set up? I'm not sure how to interpret any of these dat types except for file. I'm not sure how to use the others. What I want to do is check the image for a certain color, so I need to find out all of the pixel's color and also their location in the picture.
    Thanks!
    Blair
    Last edited by brconner; 05-30-2007 at 12:53 PM.

  4. #4
    Math wizard
    Join Date
    Dec 2006
    Location
    USA
    Posts
    582
    Code:
    			fseek(FileHandle, 14, SEEK_SET); // skip the basic file header data but read from the info header
    			fread(&ValuesBase, 1, 4, FileHandle); // bytes 0E through 11
    			BMPInfo->biSize = (DWORD)ValuesBase[0]+(DWORD)ValuesBase[1]*256+(DWORD)ValuesBase[2]*65536+(DWORD)ValuesBase[3]*16777216;
    			fread(&ValuesBase, 1, 4, FileHandle); // bytes 12 through 15
    			BMPInfo->biWidth = (long)ValuesBase[0]+(long)ValuesBase[1]*256+(long)ValuesBase[2]*65536+(long)ValuesBase[3]*16777216;
    			fread(&ValuesBase, 1, 4, FileHandle); // bytes 16 through 19
    			BMPInfo->biHeight = (long)ValuesBase[0]+(long)ValuesBase[1]*256+(long)ValuesBase[2]*65536+(long)ValuesBase[3]*16777216;
    			fread(&ValuesBase, 1, 2, FileHandle); // bytes 1A and 1B
    			BMPInfo->biPlanes = (WORD)ValuesBase[0]+(WORD)ValuesBase[1]*256;
    			fread(&ValuesBase, 1, 2, FileHandle); // bytes 1C and 1D
    			BMPInfo->biBitCount = (WORD)ValuesBase[0]+(WORD)ValuesBase[1]*256;
    			fread(&ValuesBase, 1, 4, FileHandle); // bytes 1E through 21
    			BMPInfo->biCompression = (DWORD)ValuesBase[0]+(DWORD)ValuesBase[1]*256+(DWORD)ValuesBase[2]*65536+(DWORD)ValuesBase[3]*16777216;
    			fread(&ValuesBase, 1, 4, FileHandle); // bytes 22 through 25
    			BMPInfo->biSizeImage = (DWORD)ValuesBase[0]+(DWORD)ValuesBase[1]*256+(DWORD)ValuesBase[2]*65536+(DWORD)ValuesBase[3]*16777216;
    			fread(&ValuesBase, 1, 4, FileHandle); // bytes 26 through 29
    			BMPInfo->biXPelsPerMeter = (long)ValuesBase[0]+(long)ValuesBase[1]*256+(long)ValuesBase[2]*65536+(long)ValuesBase[3]*16777216;
    			fread(&ValuesBase, 1, 4, FileHandle); // bytes 2A through 2D
    			BMPInfo->biYPelsPerMeter = (long)ValuesBase[0]+(long)ValuesBase[1]*256+(long)ValuesBase[2]*65536+(long)ValuesBase[3]*16777216;
    			fread(&ValuesBase, 1, 4, FileHandle); // bytes 2E through 31
    			BMPInfo->biClrUsed = (DWORD)ValuesBase[0]+(DWORD)ValuesBase[1]*256+(DWORD)ValuesBase[2]*65536+(DWORD)ValuesBase[3]*16777216;
    			fread(&ValuesBase, 1, 4, FileHandle); // bytes 32 through 35
    			BMPInfo->biClrImportant = (DWORD)ValuesBase[0]+(DWORD)ValuesBase[1]*256+(DWORD)ValuesBase[2]*65536+(DWORD)ValuesBase[3]*16777216;
    			
    			if (BMPInfo->biSizeImage > ArrayLength) // if not the same size for the array
    			{
    				sprintf(WarningString, "Warning:  The image is not the proper size and did not load properly.\n&#37;d bytes were expected but %d was present", ArrayLength, BMPInfo->biSizeImage); // a warning of the problem
    				MessageBox(hwnd, WarningString, "Can't find file", MB_OK | MB_ICONEXCLAMATION);
    				fread(BMPData, 1, ArrayLength, FileHandle); // read the main image data // reads in BGR format
    			}
    
    			else // if within the limits
    			{
    				fread(BMPData, 1, BMPInfo->biSizeImage, FileHandle); // read the main image data // reads in BGR format
    			}
    This is a fragment of my "LoadFile" function which loads both BMP and TGA files.
    Last edited by ulillillia; 05-30-2007 at 01:02 PM. Reason: shortened sprintf statement
    High elevation is the best elevation. The higher, the better the view!
    My computer: XP Pro SP3, 3.4 GHz i7-2600K CPU (OC'd to 4 GHz), 4 GB DDR3 RAM, X-Fi Platinum sound, GeForce 460, 1920x1440 resolution, 1250 GB HDD space, Visual C++ 2008 Express

  5. #5
    Registered User
    Join Date
    May 2007
    Posts
    16
    Could you show me the entire function and an example of how you use it? I'm having some trouble understanding parts of it.
    Thanks!
    Blair

  6. #6
    Malum in se abachler's Avatar
    Join Date
    Apr 2007
    Posts
    3,195
    Quote Originally Posted by brconner View Post
    Thank you very much, but how would I go about printing these values say to a text file? I'm not sure how to print any of these data types.
    FILE*
    BYTE*
    BYTE
    WORD
    DWORD
    Could you give me a coded example? Would there be a way I could input the pixel data in an (x,y) pixel set up? I'm not sure how to interpret any of these dat types except for file. I'm not sure how to use the others. What I want to do is check the image for a certain color, so I need to find out all of the pixel's color and also their location in the picture.
    Thanks!
    Blair
    You dont print FILE*, its just a pointer to a handle of the file you are opening. its value at run time is meaningless outside the context of that specific instance.

    Same goes for BYTE*

    BYTE is just an unsigned __int8;
    WORD is just an unsigned __int16;
    DWORD is just an unsigned long or unsigned __int32;

    Byte, Word, and Dword are just temporary variables that are meaningless outside their localized use in the program.

  7. #7
    Registered User
    Join Date
    May 2007
    Posts
    16
    Ok, that makes sense. But then how do I continue reading the bitmap after all the header stuff, so that I would be able to say that the pixel at location 5,34 has a color ...
    I don't understand how to continue inputting the pixel information.
    Thanks,
    Blair

    EDIT: Nevermind I figured it out! Thanks for all the help!
    Last edited by brconner; 05-30-2007 at 02:03 PM.

  8. #8
    Math wizard
    Join Date
    Dec 2006
    Location
    USA
    Posts
    582
    If it's a 24-bit bitmap, finding the location is fairly easy. BMPs are drawn bottom up. In a graphics edittor, the "0, 0" position is the top left corner, but in a BMP file, it's actually in the bottom left corner instead. To find the color at "5, 34", you need to know the image height. 5 is the X position which is easy to work with. 34 is the Y position. If the image was, say, 512x64, you'd take the 64, subtract the 34, and subtract 1. Why subtract 1? The bottom pixel of the image is "0, 63" in a graphics edittor but the image is 64 pixels high. Subtracting 1 accounts for this offset. For your "5, 34" position, it'd be 64-34-1 or 29. From this, you multiply it by the width of the image in pixels. Basically, the formula goes like this:

    Code:
    BaseImageLocation = (BMPHead.biHeight-PixelLocation-1)*BMPHead.biWidth*BytesPerPixel + (BMPHead.biWidth*BytesPerPixel);
    
    PixelBlueColor = ImageData[BaseImageLocation]; // BMPs are BGR order
    PixelGreenColor = ImageData[BaseImageLocation+1];
    PixelRedColor = ImageData[BaseImageLocation+2];
    This is the general idea and I may not have the correct formula (especially for the parentheses part).
    High elevation is the best elevation. The higher, the better the view!
    My computer: XP Pro SP3, 3.4 GHz i7-2600K CPU (OC'd to 4 GHz), 4 GB DDR3 RAM, X-Fi Platinum sound, GeForce 460, 1920x1440 resolution, 1250 GB HDD space, Visual C++ 2008 Express

  9. #9
    Malum in se abachler's Avatar
    Join Date
    Apr 2007
    Posts
    3,195
    What ends up in Buffer is the raw data. So for a 24 bit colormap, to find the pixel at X,Y (assuming 640x480x3) -

    Code:
    Index = (Y * 640)*3 + X*3;
     
    Blue = Buffer[Index];
    Green = Buffer[Index+1];
    Red = Buffer[Index+2];

  10. #10
    Math wizard
    Join Date
    Dec 2006
    Location
    USA
    Posts
    582
    Quote Originally Posted by abachler View Post
    What ends up in Buffer is the raw data. So for a 24 bit colormap, to find the pixel at X,Y (assuming 640x480x3) -

    Code:
    Index = (Y * 640)*3 + X*3;
     
    Blue = Buffer[Index];
    Green = Buffer[Index+1];
    Red = Buffer[Index+2];
    Well, yeah, that's a much simpler method as I checked it as well. I was only quickly coming up with the formula and didn't think through it well enough. This is more general (especially if you use 8-bit or 32-bit images in addition.

    Index = (Y*ImageWidth)*BytesPerPixel + X*BytesPerPixel;
    High elevation is the best elevation. The higher, the better the view!
    My computer: XP Pro SP3, 3.4 GHz i7-2600K CPU (OC'd to 4 GHz), 4 GB DDR3 RAM, X-Fi Platinum sound, GeForce 460, 1920x1440 resolution, 1250 GB HDD space, Visual C++ 2008 Express

  11. #11
    Registered User
    Join Date
    Mar 2007
    Location
    Bangor, Northern Ireland
    Posts
    6
    Hi All,

    There are tutorials over on this site handleing BMPs using DIBSections from webcams which may help with your own programming.

    http://uk.geocities.com/ecafin/index.html

    Regards to all,

    Eric132

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 16
    Last Post: 05-29-2009, 07:25 PM
  2. from 2D array to 1D array
    By cfdprogrammer in forum C Programming
    Replies: 17
    Last Post: 03-24-2009, 10:33 AM
  3. Replies: 6
    Last Post: 11-09-2006, 03:28 AM
  4. Class Template Trouble
    By pliang in forum C++ Programming
    Replies: 4
    Last Post: 04-21-2005, 04:15 AM
  5. Load BMP from file func
    By Death_Wraith in forum C++ Programming
    Replies: 2
    Last Post: 09-20-2004, 06:46 PM