protected async Task <List <Rectangle> > _findSubimagesMultithreaded(DirectBitmap small, byte margin, ImageSearchingOptions opts) { var xy = MathHelper.CalculateTableForGrids(opts.Threads); var rects = this.Area.Split(xy.X, xy.Y).ToArray(); var token = new cancelToken(); DataflowNotifier <List <Rectangle> > df = null; AsyncManualResetEvent res = new AsyncManualResetEvent(false); if (opts.NumberOfResults > 0) //limit search! { df = new DataflowNotifier <List <Rectangle> >(r => { var @out = !(df.Collection.Count >= opts.NumberOfResults); if (@out == false) //has reached limit { token.Cancel(); res.Set(); } return(@out); }, true); } else { df = new DataflowNotifier <List <Rectangle> >(true); } Debugging.Restart(); //Debugging.Print("Ready to fire"); int i = 0; Task[] tasks = opts.IgnoreAlphaPixels && small.Map != null ? rects.Select(r => Pool.Run(() => _findImageAlpha(small, r, small.Map.Ranges, margin, token, opts)).AndThen(t => df.Set(t))).ToArray() : rects.Select(r => Pool.Run(() => _findImage(small, r, margin, token, opts)).AndThen(t => df.Set(t))).ToArray(); await Task.WhenAny(Task.WhenAll(tasks), res.WaitAsync()); //Debugging.Print("Has Ended"); return(df.Collection.ToArray().SelectMany(l => l).ToList()); }
protected virtual unsafe List <Rectangle> _findImage(DirectBitmap small, Rectangle area, int margin, cancelToken token, ImageSearchingOptions opts) { opts = opts ?? ImageSearchingOptions.Default; var @out = new List <Rectangle>(0); int jump_small = small.PixelSize; int jump_large = this.PixelSize; byte *scan_large = (byte *)this._scan0; //[largeX+ smallX, largeY+ smallY]; byte *scan_small = (byte *)small._scan0; //[smallX, smallY]; int c, smallX = 0, smallY = 0, pix = 0; byte *s, l; //Debugging.Print($"{Thread.CurrentThread.ManagedThreadId} has started"); for (int largeY = area.Y; largeY < area.Y + area.Height; largeY++) { if (token.cancel) //here so it wont impact performance so bad { return(@out); } for (int largeX = area.X; largeX < area.X + area.Width; largeX++) { for (smallY = 0; smallY < small.Height; smallY++) { for (smallX = 0; smallX < small.Width; smallX++) { l = scan_large + (((largeX + smallX) + (largeY + smallY) * this.Width) * jump_large); s = scan_small + (smallX + smallY * small.Width) * jump_small; for (pix = 0; pix < 3; pix++) { c = l[pix] - s[pix]; //c==margin if (c > margin || c < -margin) { goto nextLoop; } } } } //If all the pixels match up, then return true and change Point location to the top left co-ordinates where it was found @out.Add(new Rectangle(largeX, largeY, small.Width, small.Height)); Debugging.Print($"{Thread.CurrentThread.ManagedThreadId} has found: {new Rectangle(largeX, largeY, small.Width, small.Height)}"); if (opts.NumberOfResults != -1 && @out.Count >= opts.NumberOfResults) { return(@out); } //Go to next pixel on large image nextLoop: ; } } //Return false if image is not found, and set an empty point /* location = Point.Empty;*/ //Debugging.Print($"{Thread.CurrentThread.ManagedThreadId} has finished"); return(@out); }