protected List <Rectangle> _findSubimages(DirectBitmap small, byte margin, ImageSearchingOptions opts) { //TODO alpha specific Debugging.Restart(); //Debugging.Print("Ready to fire"); if (small.Map != null && opts.IgnoreAlphaPixels) { if (small.Map.Ranges.Count == 0) { return(new List <Rectangle>(0)); } return(_findImageAlpha(small, this.Area, small.Map.Ranges, margin, new cancelToken(), opts)); } return(_findImage(small, this.Area, margin, new cancelToken(), opts)); }
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()); }
/// <summary> /// Searches for a bitmap inside a larger one /// </summary> /// <param name="small">Image (Bitmap) to look for </param> /// <param name="tolerance_precentage"></param> /// <param name="opts"></param> /// <returns> /// True if image was found, and changes the Point value passed to it to the top left co-ordinates of where the /// image was found /// </returns> public List <Rectangle> FindSubimages(DirectBitmap small, double tolerance_precentage, ImageSearchingOptions opts = null) { opts = opts ?? ImageSearchingOptions.Default; List <Rectangle> @out = null; byte margin = Convert.ToByte(tolerance_precentage == 0d ? 0 : Convert.ToInt32(Math.Round(255d * (tolerance_precentage / 100d)))); if (opts.AllowMultithreading) { @out = _findSubimagesMultithreaded(small, margin, opts).Result; } else { @out = _findSubimages(small, margin, opts); } ////////////////////////////////////// /// if (opts.IsSearchingInAllScreens && @out != null && @out.Count > 0) { for (int i = 0; i < @out.Count; i++) { @out[i] = @out[i].RelativeToScreenshot(); } } return(@out); }
/// <summary> /// Find images on the screen /// </summary> /// <param name="small"></param> /// <param name="tolerance_precentage"></param> /// <param name="opts"></param> /// <returns></returns> public static List <Rectangle> FindOnScreen(DirectBitmap small, double tolerance_precentage, ImageSearchingOptions opts = null) { if (opts != null) { opts.IsSearchingInAllScreens = true; } else { opts = ImageSearchingOptions.Screenshot; } return(FromScreenshot().FindSubimages(small, tolerance_precentage, opts)); }
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); }
public static Rectangle WaitUntil(this ImageSource <DirectBitmap> source, DirectBitmap small, int toleranceprecentage, ImageSearchingOptions opts = null) { opts = opts ?? ImageSearchingOptions.SingleMultithreaded; opts.NumberOfResults = 1; opts.AllowMultithreading = true; List <Rectangle> ret; do { using (var big = source.FetchFresh) ret = big.FindSubimages(small, toleranceprecentage, ImageSearchingOptions.SingleMultithreaded); } while (ret == null || ret.Count == 0); return(ret[0]); }
/// <summary> /// Finds a single subimage, null if not found. /// </summary> public static Rectangle?SingleSubimage(this ImageSource <DirectBitmap> source, DirectBitmap small, int toleranceprecentage, bool forceupdate = false, ImageSearchingOptions opts = null) { opts = opts ?? ImageSearchingOptions.SingleMultithreaded; opts.NumberOfResults = 1; opts.AllowMultithreading = true; var ret = Subimages(source, small, toleranceprecentage, forceupdate, opts)?.SingleOrDefault(); return(ret == Rectangle.Empty ? null : ret); }
public static List <Rectangle> Subimages(this ImageSource <DirectBitmap> source, DirectBitmap small, int toleranceprecentage, bool forceupdate = false, ImageSearchingOptions opts = null) { opts = opts ?? ImageSearchingOptions.Default; using (var big = forceupdate ? source.FetchFresh : source.Fetch) return(big.FindSubimages(small, toleranceprecentage, ImageSearchingOptions.SingleMultithreaded)); }
public static bool SubimageExist(this ImageSource <DirectBitmap> source, DirectBitmap small, int toleranceprecentage, bool forceupdate = false, ImageSearchingOptions opts = null) { opts = opts ?? ImageSearchingOptions.SingleMultithreaded; opts.NumberOfResults = 1; opts.AllowMultithreading = true; using (var big = forceupdate ? source.FetchFresh : source.Fetch) return((big.FindSubimages(small, toleranceprecentage, ImageSearchingOptions.SingleMultithreaded)?.Count ?? 0) > 0); }