Last time we managed to get a screenshot of the PokerStars window, now its a matter of figuring out whether there's any Cards on the Table. For this we need a function that can determine whether a smaller bitmap is contained in a larger bitmap.
I found just what I needed here: Finding a Bitmap contained inside another Bitmap.
Note, before you can use the author's code you need to allow Unsafe Code in your application because the author used pointers, which are considered unsafe in C#. To do this, right click on your project in Visual Studio, and go to properties:
Now on the Build Tab, Click the "Allow Unsafe Code" checkbox, then save-all, and rebuild your project by going Build > Build Solution.
Now you should be able to use the author's code. I modifyed the author's function slightly because I want the function to return a bool rather than a position, and I want to always use 0% tolerance because I'm searching for exact images. The function is shown below:
private bool SearchBitmap(Bitmap bigBmp, Bitmap smallBmp) { double tolerance = 0d; BitmapData smallData = smallBmp.LockBits(new Rectangle(0, 0, smallBmp.Width, smallBmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb); BitmapData bigData = bigBmp.LockBits(new Rectangle(0, 0, bigBmp.Width, bigBmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb); 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); unsafe { 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; break; } pBig++; pSmall++; } 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; break; } //If no match found, we restore the pointers and continue. else { pBig = pBigBackup; pSmall = pSmallBackup; pBig += 3; } } if (matchFound) break; pBig += bigOffset; } } bigBmp.UnlockBits(bigData); smallBmp.UnlockBits(smallData); if (location.Width != 0) { return true; } else { return false; } }
To use this function, pass in larger bitmap you are trying to search through, and the smaller bitmap you are trying to find, and the function will return true if the smaller Bitmap was found within the larger one, or false if it was not found.
To Test whether the code is working properly we will use this table image PokerTable.bmp, and run two different tests. The first Test will check if a seven of spades exists on the table, and the second test will check if the seven of clubs exists on the table. To run the image comparisons, you'll need the bitmaps of the individual cards I attached in the last post: 52CardBitmaps.zip
For these tests, I'm going to put my PokerTable.bmp, S7.bmp, and C7.bmp into the Debug folder in my C# Project.

Now in Visual studio, I'll create a new button to run these tests, and in the buttons Click Event Code put this:
To Test whether the code is working properly we will use this table image PokerTable.bmp, and run two different tests. The first Test will check if a seven of spades exists on the table, and the second test will check if the seven of clubs exists on the table. To run the image comparisons, you'll need the bitmaps of the individual cards I attached in the last post: 52CardBitmaps.zip
For these tests, I'm going to put my PokerTable.bmp, S7.bmp, and C7.bmp into the Debug folder in my C# Project.
![]() |
PokerTable.bmp |
![]() |
C7.bmp |
![]() |
S7.bmp |
Now in Visual studio, I'll create a new button to run these tests, and in the buttons Click Event Code put this:
private void button2_Click(object sender, EventArgs e) { //Define Bitmap Images from filepaths Bitmap PokerTable = new Bitmap(Application.StartupPath + "//PokerTable.bmp"); Bitmap S7 = new Bitmap(Application.StartupPath + "//S7.bmp"); Bitmap C7 = new Bitmap(Application.StartupPath + "//C7.bmp"); //Check for Seven of Spades on the table if (SearchBitmap(PokerTable, S7)) { Console.WriteLine("Seven of Spades was found on the table."); } else { Console.WriteLine("Seven of Spades was not found on the table."); } //Check for Seven of Clubs on the table if (SearchBitmap(PokerTable, C7)) { Console.WriteLine("Seven of Clubs was found on the table."); } else { Console.WriteLine("Seven of Clubs was not found on the table."); } }
When you click this button, you should see the following Console output:
This verifys that the search Code is working properly. The program matched up the Bitmap of the Seven of spades with the one on the table, and failed to see the seven of clubs.
In the next Post we will shrink down the area where the program is looking for cards to make the search more effiecient. Also it will give the program the ability to tell the difference between cards in your hand, and shared cards.