Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>First, there is a problem with the <code>findmatch</code> loop. You shouldn't just use the haystack image as an array, because you need to subtract needle's width and height from right and bottom respectively:</p> <pre><code>public Point? findmatch(int[] haystack, int[] needle) { var firstpixel = needle[0]; for (int y = 0; y &lt; haystack_height - needle_height; y++) for (int x = 0; x &lt; haystack_width - needle_width; x++) { if (haystack[y * haystack_width + x] == firstpixel) { var matched = checkmatch(haystack, needle, x, y); if (matched) return (new Point(x, y)); } } return null; } </code></pre> <p>That should probably solve the problem. Also, keep in mind that there might be <strong>multiple matches</strong>. For example, if "needle" is a completely white rectangle portion of a window, there will most likely be many matches in the entire screen. If this is a possibility, modify your <code>findmatch</code> method to continue searching for results after the first one is found:</p> <pre><code>public IEnumerable&lt;Point&gt; FindMatches(int[] haystack, int[] needle) { var firstpixel = needle[0]; for (int y = 0; y &lt; haystack_height - needle_height; y++) for (int x = 0; x &lt; haystack_width - needle_width; x++) { if (haystack[y * haystack_width + x] == firstpixel) { if (checkmatch(haystack, needle, x, y)) yield return (new Point(x, y)); } } } </code></pre> <p>Next, you need to keep a habit of manually disposing all objects which implement <code>IDisposable</code>, which you have created yourself. <code>Bitmap</code> and <code>Graphics</code> are such objects, meaning that your <code>screenshot</code> method needs to be modified to wrap those objects in <code>using</code> statements:</p> <pre><code>private int[] screenshot(int x, int y, int width, int height) { // dispose 'bmp' after use using (var bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb)) { // dispose 'g' after use using (var g = Graphics.FromImage(bmp)) { g.CopyFromScreen(x, y, 0, 0, bmp.Size); var bmd = bmp.LockBits( new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat); var ptr = bmd.Scan0; // as David pointed out, "bytes" might be // a bit misleading name for a length of // a 32-bit int array (so I've changed it to "len") var len = bmd.Stride * bmp.Height / 4; var result = new int[len]; Marshal.Copy(ptr, result, 0, len); bmp.UnlockBits(bmd); return result; } } } </code></pre> <p>The rest of the code seems ok, with the remark that it won't be very efficient for certain inputs. For example, you might have a large solid color as your desktop's background, which might result in many <code>checkmatch</code> calls. </p> <p>If performance is of interest to you, you might want to check different ways to speed up the search (something like a modified <a href="http://en.wikipedia.org/wiki/Rabin-Karp_string_search_algorithm" rel="nofollow">Rabin-Karp</a> comes to mind, but I am sure there are some existing algorithms which ensure that invalid candidates are skipped immediately).</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload