Click here to Skip to main content
11,720,785 members (77,148 online)
Click here to Skip to main content

Comparing Two Bitmaps for Equality

, 19 Dec 2006 CPOL 60.7K 2 37
Rate this:
Please Sign up or sign in to vote.
Code snippet that compares two HBITMAP handles to see if the bitmaps they contain are the same

Introduction

Presented here is a simple method to compare two HBITMAP handles to see if they contain the same bitmap. The code itself is nothing fancy, so I will just include it in the article text. No separate download or demo application is needed.

How to Compare Two Bitmaps for Equality

The first thing to do is compare the HBITMAP handles themselves. If they are the same handle, then the two bitmaps are obviously equal. If one of the handles is NULL, then they are obviously not equal. If the HBITMAP handles are different and not NULL, then use GetDIBits to fill two BITMAPINFO structures -- one for each bitmap -- and compare the BITMAPINFOHEADERs. If the BITMAPINFOHEADERs contain different data, then the bitmaps are different. If they contain the same data, then the next step is to compare the actual bitmap data bits.

The Code

/////////////////////////////////////////////////////////////////////////////
//
//  CompareBitmaps
//    Compares two HBITMAPs to see if they contain the same image
//
//  Parameters :
//    HBitmapLeft  [in] : The HBITMAP handles that are to be compared
//    HBitmapRight [in] :
//
//  Returns :
//    true if the bitmaps are the same
//    false if they are different
//
/////////////////////////////////////////////////////////////////////////////


bool CompareBitmaps(HBITMAP HBitmapLeft, HBITMAP HBitmapRight)
{
    if (HBitmapLeft == HBitmapRight)
    {
        return true;
    }

    if (NULL == HBitmapLeft || NULL == HBitmapRight)
    {
        return false;
    }

    bool bSame = false;

    HDC hdc = GetDC(NULL);
    BITMAPINFO BitmapInfoLeft = {0};
    BITMAPINFO BitmapInfoRight = {0};

    BitmapInfoLeft.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    BitmapInfoRight.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);

    if (0 != GetDIBits(hdc, HBitmapLeft, 0, 0, NULL, &BitmapInfoLeft, DIB_RGB_COLORS) &&
        0 != GetDIBits(hdc, HBitmapRight, 0, 0, NULL, &BitmapInfoRight, DIB_RGB_COLORS))
    {
        // Compare the BITMAPINFOHEADERs of the two bitmaps

        if (0 == memcmp(&BitmapInfoLeft.bmiHeader, &BitmapInfoRight.bmiHeader, 
            sizeof(BITMAPINFOHEADER)))
        {
            // The BITMAPINFOHEADERs are the same so now compare the actual bitmap bits

            BYTE *pLeftBits = new BYTE<BitmapInfoLeft.bmiHeader.biSizeImage>;
            BYTE *pRightBits = new BYTE<BitmapInfoRight.bmiHeader.biSizeImage>;
            BYTE *pByteLeft = NULL;
            BYTE *pByteRight = NULL;

            PBITMAPINFO pBitmapInfoLeft = &BitmapInfoLeft;
            PBITMAPINFO pBitmapInfoRight = &BitmapInfoRight;

            // calculate the size in BYTEs of the additional

            // memory needed for the bmiColor table

            int AdditionalMemory = 0;
            switch (BitmapInfoLeft.bmiHeader.biBitCount)
            {
            case 1:
                AdditionalMemory = 1 * sizeof(RGBQUAD);
                break;
            case 4:
                AdditionalMemory = 15 * sizeof(RGBQUAD);
                break;
            case 8:
                AdditionalMemory = 255 * sizeof(RGBQUAD);
                break;
            case 16:
            case 32:
                AdditionalMemory = 2 * sizeof(RGBQUAD);
            }

            if (AdditionalMemory)
            {
                // we have to allocate room for the bmiColor table that will be

                // attached to our BITMAPINFO variables

                pByteLeft = new BYTE[sizeof(BITMAPINFO) + AdditionalMemory];
                if (pByteLeft)
                {
                    memset(pByteLeft, 0, sizeof(BITMAPINFO) + AdditionalMemory);
                    memcpy(pByteLeft, pBitmapInfoLeft, sizeof(BITMAPINFO));
                    pBitmapInfoLeft = (PBITMAPINFO)pByteLeft;
                }

                pByteRight = new BYTE[sizeof(BITMAPINFO) + AdditionalMemory];
                if (pByteRight)
                {
                    memset(pByteRight, 0, sizeof(BITMAPINFO) + AdditionalMemory);
                    memcpy(pByteRight, pBitmapInfoRight, sizeof(BITMAPINFO));
                    pBitmapInfoRight = (PBITMAPINFO)pByteRight;
                }
            }

            if (pLeftBits && pRightBits && pBitmapInfoLeft && pBitmapInfoRight)
            {
                // zero out the bitmap bit buffers

                memset(pLeftBits, 0, BitmapInfoLeft.bmiHeader.biSizeImage);
                memset(pRightBits, 0, BitmapInfoRight.bmiHeader.biSizeImage);

                // fill the bit buffers with the actual bitmap bits

                if (0 != GetDIBits(hdc, HBitmapLeft, 0, 
                    pBitmapInfoLeft->bmiHeader.biHeight, pLeftBits, pBitmapInfoLeft, 
                    DIB_RGB_COLORS) && 0 != GetDIBits(hdc, HBitmapRight, 0, 
                    pBitmapInfoRight->bmiHeader.biHeight, pRightBits, pBitmapInfoRight, 
                    DIB_RGB_COLORS))
                {
                    // compare the actual bitmap bits of the two bitmaps

                    bSame = 0 == memcmp(pLeftBits, pRightBits, 
                        pBitmapInfoLeft->bmiHeader.biSizeImage);
                }
            }

            // clean up

            delete[] pLeftBits;
            delete[] pRightBits;
            delete[] pByteLeft;
            delete[] pByteRight;
        }
    }

    ReleaseDC(NULL, hdc);

    return bSame;
}

History

  • 19 December, 2006 -- Original version posted
  • 12 March, 2008 -- Article edited and moved to The Code Project main article base

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

PJ Arends
President
Canada Canada
No Biography provided

You may also be interested in...

Comments and Discussions

 
QuestionCan we use this for cursor? Pin
bala boy26-Aug-14 0:11
memberbala boy26-Aug-14 0:11 
GeneralSmall Addition - detect minor changes Pin
Alexander Shilonosov10-Jun-10 0:16
memberAlexander Shilonosov10-Jun-10 0:16 
Newsported to C [modified] Pin
Mikke828-Jan-10 13:49
memberMikke828-Jan-10 13:49 
Questionam I doing somthing wrong? It crashes. Pin
Member 137233911-Mar-08 4:09
memberMember 137233911-Mar-08 4:09 
GeneralRe: am I doing somthing wrong? It crashes. Pin
PJ Arends12-Mar-08 4:43
memberPJ Arends12-Mar-08 4:43 
GeneralExtending this Idea Pin
ceejeeb27-Jan-07 0:36
memberceejeeb27-Jan-07 0:36 
GeneralRe: Extending this Idea Pin
PJ Arends27-Jan-07 9:52
memberPJ Arends27-Jan-07 9:52 
GeneralRe: Extending this Idea Pin
ceejeeb28-Jan-07 2:43
memberceejeeb28-Jan-07 2:43 
GeneralRe: Extending this Idea Pin
PJ Arends28-Jan-07 9:17
memberPJ Arends28-Jan-07 9:17 
GeneralRe: Extending this Idea Pin
ceejeeb5-Feb-07 0:35
memberceejeeb5-Feb-07 0:35 
GeneralRe: Extending this Idea Pin
PJ Arends6-Feb-07 9:58
memberPJ Arends6-Feb-07 9:58 
GeneralRe: Extending this Idea Pin
ceejeeb7-Feb-07 3:55
memberceejeeb7-Feb-07 3:55 
GeneralRe: Extending this Idea Pin
PJ Arends7-Feb-07 7:43
memberPJ Arends7-Feb-07 7:43 
GeneralRe: Extending this Idea Pin
Rafal Struzyk11-Jul-07 7:09
memberRafal Struzyk11-Jul-07 7:09 
GeneralRe: Extending this Idea Pin
PJ Arends23-Mar-07 18:56
memberPJ Arends23-Mar-07 18:56 
GeneralGreat but far too simple Pin
IntVestor21-Dec-06 6:53
memberIntVestor21-Dec-06 6:53 
GeneralRe: Great but far too simple Pin
PJ Arends21-Dec-06 7:04
memberPJ Arends21-Dec-06 7:04 
GeneralRe: Great but far too simple Pin
Lampros G10-Jan-07 5:41
memberLampros G10-Jan-07 5:41 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150901.1 | Last Updated 19 Dec 2006
Article Copyright 2006 by PJ Arends
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid