Click here to Skip to main content
14,268,217 members

Finding a Bitmap contained inside another Bitmap

Rate this:
4.73 (19 votes)
Please Sign up or sign in to vote.
4.73 (19 votes)
10 Mar 2010CPOL
A method to look for a small Bitmap that is contained inside a bigger Bitmap.



Several days ago, I was trying to find a way to locate a small Bitmap that I knew was contained in another, bigger Bitmap. I found methods on the Internet used to transform a Bitmap, to filter it, to resize/resample... but not what I needed.

After asking for some help here in CodeProject, I learnt how to go through a Bitmap using LockBits() (instead of the GetPixel() and SetPixel() methods, which are much slower), thanks to this article from Christian Graus, and finally, I could make my own (basic) algorithm to perform this search.

Comments, bug reports, and suggestions to improve performance will be highly appreciated since this is my first article here. Thanks to Basiuk for his bug report (the code is already updated to fix it), and to TF_Productions for his suggestions, all of which I hope I could implement in a future.


Nothing special, I think.

Using the code

If you want to use it in your application, you only need the searchBitmap() method:

private Rectangle searchBitmap(Bitmap smallBmp, Bitmap bigBmp, double tolerance)
    BitmapData smallData = 
      smallBmp.LockBits(new Rectangle(0, 0, smallBmp.Width, smallBmp.Height), 
    BitmapData bigData = 
      bigBmp.LockBits(new Rectangle(0, 0, bigBmp.Width, bigBmp.Height), 

    int smallStride = smallData.Stride;
    int bigStride = bigData.Stride;

    int bigWidth = bigBmp.Width;
    int bigHeight = bigBmp.Height - smallBmp.Height + 1;
    int smallWidth = smallBmp.Width * 3;
    int smallHeight = smallBmp.Height;

    Rectangle location = Rectangle.Empty;
    int margin = Convert.ToInt32(255.0 * tolerance);

        byte* pSmall = (byte*)(void*)smallData.Scan0;
        byte* pBig = (byte*)(void*)bigData.Scan0;

        int smallOffset = smallStride - smallBmp.Width * 3;
        int bigOffset = bigStride - bigBmp.Width * 3;

        bool matchFound = true;

        for (int y = 0; y < bigHeight; y++)
            for (int x = 0; x < bigWidth; x++)
                byte* pBigBackup = pBig;
                byte* pSmallBackup = pSmall;

                //Look for the small picture.
                for (int i = 0; i < smallHeight; i++)
                    int j = 0;
                    matchFound = true;
                    for (j = 0; j < smallWidth; j++)
                        //With tolerance: pSmall value should be between margins.
                        int inf = pBig[0] - margin;
                        int sup = pBig[0] + margin;
                        if (sup < pSmall[0] || inf > pSmall[0])
                            matchFound = false;


                    if (!matchFound) break;

                    //We restore the pointers.
                    pSmall = pSmallBackup;
                    pBig = pBigBackup;

                    //Next rows of the small and big pictures.
                    pSmall += smallStride * (1 + i);
                    pBig += bigStride * (1 + i);

                //If match found, we return.
                if (matchFound)
                    location.X = x;
                    location.Y = y;
                    location.Width = smallBmp.Width;
                    location.Height = smallBmp.Height;
                //If no match found, we restore the pointers and continue.
                    pBig = pBigBackup;
                    pSmall = pSmallBackup;
                    pBig += 3;

            if (matchFound) break;

            pBig += bigOffset;


    return location;

It receives two Bitmaps (the smaller one and the bigger one), and the tolerance that should apply when searching (0.0 meaning exact match). It returns a Rectangle with the location of the smaller image within the bigger one.

If no match is found, the width and the height of the Rectangle will be zero:

Rectangle location = searchBitmap(bitmap1, bitmap2, tolerance);
if (location.Width != 0)
     //Do something.

Understanding the code

First of all, you should read the above mentioned article from Christian Graus.

What a Bitmap is for us

The key is that you must understand that a Bitmap is no longer an object with pixels ordered in columns and rows, but a series of bytes in your computer memory. A "row" of three pixels of a Bitmap could be seen as, for example, these bytes:

255 0 0 | 0 255 0 | 0 0 255 | X ... X

What we have is:

  • Three bytes per pixel, each one for one color component of the pixel. The order of the bytes is BGR (blue component, green component, red component), due to the fact that PixelFormat.Format24bppRgb shows BGR instead of RGB.
  • The first pixel is BLUE in our example.
  • The second pixel is GREEN in our example.
  • And, the third and last pixel is RED in our example.

They are followed by a variable number of bytes "X ... X", which I have named "offset" in the code, and are used for padding. We are not interested in their contents. You can see how the offset is calculated in the famous article from Christian Graus.

If we had a bitmap with two rows, these would be seen as follows:

255 0 0 | 0 255 0 | 0 0 255 | X ... X | 192 0 192 | 128 128 0 | 0 0 128 | X ... X

So, if we are looking at one "pixel" and want to go to the next row, what we need to do is move forward 9 bytes (3 bytes per pixel, 3 pixels per row) plus the offset. It is done in the following line of code:

pBig += bigStride * (1 + i);

which is equivalent to:

pBig += (bigWidth * 3 + bigOffset) * (1 + i);

Of course, if you want to move to the next pixel, you must move forward 3 bytes (or the offset, if you are at the last pixel of a row):

pBig += 3;
pBig += bigOffset;

The algorithm

Once the previous point is understood, I think the rest is pretty self-explanatory:

  1. The method goes through the bigger Bitmap, "row" by "row", searching for "pixels" that match those of the first "row" of the smaller Bitmap.
  2. When a match is found, we go to the next "row" of the bigger Bitmap and the next "row" of the smaller one (still staying at the same "columns"), and compare them.
  3. If they're not equal (considering the tolerance), we restore the pointers and continue searching from where we are.
  4. If they're equal (considering the tolerance), we repeat step 2 until we have compared all the "rows" of the smaller Bitmap. At that point, if we have a match, we return the corresponding Rectangle.

Sample application

The application is very simple: you choose two bitmaps, choose the tolerance level, and press the "Search" button.


The output will be the Rectangle in which the smaller Bitmap is located inside the bigger one.

The "Auto" check can be useful: it starts searching with tolerance = 0 (exact match), and increases it in a loop, searching again and again until a match is found or the maximum tolerance is reached. Note that, with bigger tolerances, the time increases.

If you want to search only for an exact match, use tolerance = 0.0.


When to use and when not

The above method is useful for finding a small Bitmap (like an icon or a button) inside a bigger one (like a window capture). If you look for exact matches or use low tolerances, you can get the output in a few milliseconds (15-30 ms.), which is much faster than using algorithms with the GetPixel() and SetPixel() methods.

The problem is when you want to look for a big Bitmap contained in a huge Bitmap. The time increases a lot with the size of the images, so be careful choosing the images and the tolerance.


  • 31.07.2009 - Posted (first version).
  • 10.03.2010 - Updated source code.


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


About the Author

Spain Spain
No Biography provided

Comments and Discussions

QuestionThank You. That's a great job. Pin
Murad Tulunay23-Mar-17 21:29
memberMurad Tulunay23-Mar-17 21:29 
AnswerRe: Thank You. That's a great job. Pin
Arvins23-Aug-17 18:37
memberArvins23-Aug-17 18:37 
PraiseFor Android Code for this Pin
chintak1233215-Jan-17 20:31
memberchintak1233215-Jan-17 20:31 
PraiseGreat code ! Pin
Member 790025610-Oct-16 7:58
memberMember 790025610-Oct-16 7:58 
QuestionRotated image search Pin
Member 1250208522-Sep-16 0:06
memberMember 1250208522-Sep-16 0:06 
QuestionCan I have it in Java? Pin
Member 790025623-Jul-16 22:31
memberMember 790025623-Jul-16 22:31 
QuestionAdding transparency Pin
Member 114676183-Jan-16 5:57
memberMember 114676183-Jan-16 5:57 
Questioncan i have this code in Pin
Member 1065296913-Jul-15 18:39
memberMember 1065296913-Jul-15 18:39 
AnswerRe: can i have this code in Pin
dazza00023-Nov-15 15:06
memberdazza00023-Nov-15 15:06 
GeneralMy vote of 5 Pin
Sturms27-Jan-15 8:57
memberSturms27-Jan-15 8:57 
QuestionStraight-forward optimization: KMP Pin
infinite-recursion10-Oct-13 1:58
memberinfinite-recursion10-Oct-13 1:58 
QuestionHandle multiple image finds Pin
Michael McBrien6-Dec-11 20:29
memberMichael McBrien6-Dec-11 20:29 
AnswerRe: Handle multiple image finds Pin
Italo Gomes6-Jan-14 6:03
memberItalo Gomes6-Jan-14 6:03 
QuestionHot to fix for another formats .jpg .png .tif? Pin
jgui27-Mar-11 19:34
memberjgui27-Mar-11 19:34 
GeneralThis is great Pin
Gopher201117-Mar-11 0:10
memberGopher201117-Mar-11 0:10 
GeneralError in algorithm Pin
basiuk9-Mar-10 4:09
memberbasiuk9-Mar-10 4:09 
GeneralRe: Error in algorithm [modified] Pin
verence3339-Mar-10 7:39
memberverence3339-Mar-10 7:39 
GeneralRe: Error in algorithm Pin
basiuk9-Mar-10 20:48
memberbasiuk9-Mar-10 20:48 
GeneralRe: Error in algorithm Pin
verence3339-Mar-10 21:29
memberverence3339-Mar-10 21:29 
GeneralRe: Error in algorithm Pin
basiuk9-Mar-10 22:02
memberbasiuk9-Mar-10 22:02 
GeneralRe: Error in algorithm Pin
verence3339-Mar-10 23:10
memberverence3339-Mar-10 23:10 
GeneralRe: Error in algorithm Pin
verence33310-Mar-10 7:12
memberverence33310-Mar-10 7:12 
GeneralNice but inefficient. Pin
tobywf4-Aug-09 5:31
membertobywf4-Aug-09 5:31 
GeneralRe: Nice but inefficient. Pin
verence3334-Aug-09 19:54
memberverence3334-Aug-09 19:54 
GeneralRe: Nice but inefficient. Pin
pclion5-Aug-09 7:31
memberpclion5-Aug-09 7:31 

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.

Posted 31 Jul 2009


42 bookmarked