!7 concept Grab { new Ref screenshot; Pt point; new MultiSet sizes; } p-substance-thread { shootScreen_useScrot = true; // method without black spots db(); awt { showControls(jCenteredLine( jbutton("Grab", "grab"), jbutton("Find", rThread("find")))); final JTable table = showConceptsTable(Grab); addToWindow(table, tableDependButton(table, "Show", r { visualize(selectedConcept(table, Grab)); })); } } svoid grab { trackOneClick(voidfunc(final Point p) { thread { sleep(500); // allow screen behind red dot to be repainted Grab grab = cnew(Grab, screenshot := new PNGFile(shootScreenBufferedImage()), point := new Pt(p) ); infoBox("Grabbed! " + grab.id); } }); } svoid find { float ppt = 0.1f; // per pixel tolerance RGBImage imgB = rgbShootScreen(); int w = imgB.w(), h = imgB.h(); for (Grab grab) { print ("Searching " + grab.id + "..."); RGBImage imgA = new RGBImage(grab.screenshot->getImage()); Pt p = grab.point; int col = imgA.getInt(p.x, p.y); new MultiSet matches; for y to h: for x to w: if (rgbDiff(col, imgB.getInt(x, y)) <= ppt) { Rect r1 = new Rect(p.x, p.y, 1, 1); Rect r2 = new Rect(x, y, 1, 1); Rect r = translateRect(rgbExpandMatch(imgA, imgB, r1, r2, ppt), -p.x, -p.y); matches.add(r); } L matchesList = sortByCalculatedFieldDesc(keys(matches), f rectPixels); Rect r = first(matchesList); if (r != null) print("Largest match: " + rectPixels(r) + " pixels. " + n(matchesList, "matches") + ": " + matchesList); else print("No match"); grab.sizes.addAll(matches); grab.change(); } print("Done finding"); } static int visW = 200, visH = 200; svoid visualize(Grab grab) { RGBImage img = new RGBImage(grab.screenshot->getImage()); Collection rects = keys(grab.sizes); Pt p = grab.point; Rect clip = intersectRects(new Rect(0, 0, img.w(), img.h()), new Rect(p.x-visW/2, p.y-visH/2, visW, visH)); img = img.clip(clip); rgbMarkPoint(img, p.x-clip.x, p.y-clip.y); rects = translateRects(rects, p.x-clip.x, p.y-clip.y); quickShowImage("Grab " + grab.id, rgbVisualizeRectsZoomed(img, rects)); }