Click here to Skip to main content
15,879,474 members
Articles / Desktop Programming / MFC
Article

Comparing Two Bitmaps for Equality

Rate me:
Please Sign up or sign in to vote.
3.60/5 (13 votes)
19 Dec 2006CPOL 100.4K   37   18
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

C++
/////////////////////////////////////////////////////////////////////////////
//
//  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)


Written By
President
Canada Canada
Father of two, brother of two, child of two.
Spouse to one, uncle to many, friend to lots.
Farmer, carpenter, mechanic, electrician, but definitely not a plumber.
Likes walks with the wife, board games, card games, travel, and camping in the summer.
High school graduate, college drop-out.
Hobby programmer who knows C++ with MFC and the STL.
Has dabbled with BASIC, Pascal, Fortran, COBOL, C#, SQL, ASM, and HTML.
Realized long ago that programming is fun when there is nobody pressuring you with schedules and timelines.

Comments and Discussions

 
QuestionCan we use this for cursor? Pin
bala boy26-Aug-14 0:11
bala boy26-Aug-14 0:11 
GeneralSmall Addition - detect minor changes Pin
Alexander Silonosov10-Jun-10 0:16
Alexander Silonosov10-Jun-10 0:16 
Newsported to C [modified] Pin
Mikke828-Jan-10 13:49
Mikke828-Jan-10 13:49 
Questionam I doing somthing wrong? It crashes. Pin
Member 137233911-Mar-08 4:09
Member 137233911-Mar-08 4:09 
GeneralRe: am I doing somthing wrong? It crashes. Pin
PJ Arends12-Mar-08 4:43
professionalPJ Arends12-Mar-08 4:43 
GeneralExtending this Idea Pin
ceejeeb27-Jan-07 0:36
ceejeeb27-Jan-07 0:36 
GeneralRe: Extending this Idea Pin
PJ Arends27-Jan-07 9:52
professionalPJ Arends27-Jan-07 9:52 
GeneralRe: Extending this Idea Pin
ceejeeb28-Jan-07 2:43
ceejeeb28-Jan-07 2:43 
GeneralRe: Extending this Idea Pin
PJ Arends28-Jan-07 9:17
professionalPJ Arends28-Jan-07 9:17 
GeneralRe: Extending this Idea Pin
ceejeeb5-Feb-07 0:35
ceejeeb5-Feb-07 0:35 
GeneralRe: Extending this Idea Pin
PJ Arends6-Feb-07 9:58
professionalPJ Arends6-Feb-07 9:58 
GeneralRe: Extending this Idea Pin
ceejeeb7-Feb-07 3:55
ceejeeb7-Feb-07 3:55 
GeneralRe: Extending this Idea Pin
PJ Arends7-Feb-07 7:43
professionalPJ Arends7-Feb-07 7:43 
GeneralRe: Extending this Idea Pin
Rafal Struzyk11-Jul-07 7:09
Rafal Struzyk11-Jul-07 7:09 
GeneralRe: Extending this Idea Pin
PJ Arends23-Mar-07 18:56
professionalPJ Arends23-Mar-07 18:56 
GeneralGreat but far too simple Pin
IntVestor21-Dec-06 6:53
IntVestor21-Dec-06 6:53 
GeneralRe: Great but far too simple Pin
PJ Arends21-Dec-06 7:04
professionalPJ Arends21-Dec-06 7:04 
GeneralRe: Great but far too simple Pin
Lampros Giampouras10-Jan-07 5:41
Lampros Giampouras10-Jan-07 5:41 
That's what the PSNR calculation is all about..
It will tell you if two images are exactly the same, and if not, how different are they.

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

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