Uses 1482K of libraries. Click here for Pure Java version (12308L/65K).
!7 need latest onSelectedItem. !include early #1033506 // Compact Module Include Gazelle V module GazelleV > DynPrintLogAndEnabled { /*switchable int x1; switchable int y1; switchable int w = screenWidth(); switchable int h = screenHeight();*/ switchable double maxFPS = 10; switchable int previewWidth = 200; switchable double statsEvery = 5; switchable volatile bool brokenMethod; int lookAtScreen; S previewMode; int gridRows = 20; bool scaleDownPreviewImage; int previewPosterization = 256; S uiURL = "Home"; //bool deepCompression; PersistableThrowable lastProcessingError; transient WithTimestamp<OKOrError<BufferedImage>> lastScreen; transient new Average screenShotTime; transient new Average iiTime; transient Timestamp loopStarted; transient Sleeping screenShotCountdown; transient long screenShotCountdownTotalSleepTime; //transient ImageSurface imageSurface; transient IIImageSurface imageSurface; transient Throwable currentProcessingError; transient JButton popDownButton; transient JComponent topControls; transient long screenShotsTaken; transient double fps; transient Compression ongoingCompression, completedCompression; transient S longTermCompressionProbability; transient S longTermCompressionScore; transient JComponent topControls2; transient JTabbedPane tabs; transient ThreadPool threadPool; transient SingleComponentPanel mainArea; // key: ui URL // value: component maker transient Map<S, IF0<JComponent>> uiMap = syncCIMap(); // ping source for everything we do in the background, including // analyzing current screen. // normally limited to 50% of one core. transient PingSource backgroundPingSource; transient OnOffOscillator onOffOscillator; Rect area() { ret screenBounds(min(lookAtScreen, screenCount()-1)); } class Compression { settable BufferedImage image; settable BWIntegralImage ii; CompressionSearch_AnyType search; int baseLineLength; // length of trivial compression GridCodec1 codec; double compressionPercentage; S score() { var submission = search?.bestSubmission(); Int compressedSize = or(submission.compressedSize(), baseLineLength); compressionPercentage = 100-doubleRatio(compressedSize, baseLineLength)*100; ret iround(compressionPercentage) + "%"; } IProbabilisticScheduler scheduler() { ret search?.scheduler(); } S probability() { var scheduler = scheduler(); if (scheduler == null) ret "-"; var prob = scheduler.lastExecutedProbability(); ret formatDouble(prob, 3); } event compressionDone; run { int lHex = pixelCount(image)*8; baseLineLength = calculateLengthOfFunctionCall imageFromHex(lHex+2); print(+baseLineLength); codec = new GridCodec1(image); codec.rows = gridRows; search = codec.forward(); //showImage(codec.renderCellsLinearly()); repeat 60 { stepForNSeconds(1, search); //print(stepCount := search.scheduler().stepCount()); setFields( longTermCompressionProbability := probability(), longTermCompressionScore := score()); } try { compressionDone(); L<IJavaExpr> cellCompressions = codec.strat.codeForElements(); //showText("Compression", lines(map shorten_str(cellCompressions))); /*S code = str(codec.winnerCode()); S name = "Screenshot " + ymdMinusHMS(); File f = makeFileNameUnique_beforeExtension( javaxDataDir("Compressed Screenshots/" + name + ".javax")); saveTextFile(f, code); printFileInfo(f); saveGZTextFile(f = replaceExtension(f, ".jgz"), code); printFileInfo(f);*/ /* print("Evaling " + nChars(code)); //LL<Int> lol = cast dm_javaEval(code); BufferedImage restored = cast dm_javaEval(code); assertImagesIdentical(restored, image); print("Image restored!"); dm_showImage("Restored from " + nChars(code), restored); */ } catch e { printStackTrace(e); } } void drawOverlay(ImageSurface is, Graphics2D g) pcall { codec.drawOverlay(is, g); } int gridCols() { ret widthForHeight(ii.getWidth(), ii.getHeight(), gridRows); } } // end of Compression int gridCols(MakesBufferedImage ii) { ret widthForHeight(ii.getWidth(), ii.getHeight(), gridRows); } start { if (threadPool == null) threadPool = maxThreadPool(); backgroundPingSource = new PingSource(threadPool, "Background"); onOffOscillator = new OnOffOscillator(backgroundPingSource); ownResource(onOffOscillator); onOffOscillator.start(); componentFieldsToKeep = litset("tabs"); dm_registerAs_direct gazelleV(); dm_watchField enabled(r { if (enabled) dm_reload(); }); // TODO: react to event sent by OS dm_doEvery(1.0, r { if (dm_moduleIsPoppedOut()) adjustUIForPoppedOutWindow(); }); print("Screen bounds: " + allScreenBounds()); initUIMap(); // We are making some UI elements even if the module is hidden // because that's easier. tabs = jtabs( "Log", super.visualize(), "Local Data", jcenteredlabel("TODO")); dm_doEvery(min(statsEvery, 10.0), statsEvery, r { if (enabled) printStats(); }); loopStarted = tsNow(); shootAndAnalyze(); } void shootAndAnalyze { backgroundPingSource.do(r shootAndAnalyze_impl); } void shootAndAnalyze_impl enter { if (!enabled) ret; var targetTime = tsNow().plus(1.0/maxFPS); long time = nanoTime(); try { lastScreen = withTimestamp(okOrError(-> screenshot(area()))); ++screenShotsTaken; setField(fps := doubleRatio(screenShotsTaken, elapsedSeconds(loopStarted))); screenShotTime.add(nanosToSeconds(nanoTime()-time)); time = nanoTime(); ping(); if (lastScreen->isOK()) { var img = lastScreen!!; var ii = BWIntegralImage(img); //var ii = BWIntegralImage_luminosity(lastScreen!!); iiTime.add(nanosToSeconds(nanoTime()-time)); if (!deepCompression()) showPreview(ii, null); else startCompression(ii); } cpuTotal(); currentProcessingError = null; } catch print e { setField(lastProcessingError := currentProcessingError = e); //sleepSeconds(60); // errors in processing are no good } screenShotCountdown = sleeper().doLater(targetTime, r shootAndAnalyze); screenShotCountdownTotalSleepTime += screenShotCountdown.remainingMS(); } bool deepCompression() { ret !scaleDownPreviewImage; } void showPreview(BWIntegralImage ii, Compression completedCompression) { IBWIntegralImage ii2 = ii; if (scaleDownPreviewImage) { ii2 = ScaledIBWIntegralImage(gridCols(ii2), gridRows, ii2); ii2 = TruncatedIBWIntegralImage(ii2); if (previewPosterization < 256) imageSurface?.setImage(posterizeIBWImage(previewPosterization, ii2)); else imageSurface?.setImage(ii2); imageSurface.setOverlay(null); } else { imageSurface?.setImage(completedCompression.ii, completedCompression.image); if (completedCompression != null) imageSurface.setOverlay(g -> completedCompression.drawOverlay(imageSurface, g)); } } void startCompression(BWIntegralImage ii) { if (ongoingCompression == null) { ping(); ongoingCompression = new Compression() .image(lastScreen!!) .ii(ii); ongoingCompression.onCompressionDone(-> { completedCompression = ongoingCompression; ongoingCompression = null; showPreview(ii, completedCompression); }); ongoingCompression.run(); } } void printStats() { print(stats()); } S stats() { var screen = lastScreen?!; ret formatColonProperties_noNulls( "Monitored area", area(), "Error", screen?.getError(), "Last screenshot taken", lastScreen?.timeStamp(), "Average time to take a screenshot", screenShotTime, "Average time to make integral image", iiTime, "Capacity left in first core", percentRatioStrOneDigit(freeInCore()), "Total CPU used", cpuTotal(), ); } S cpuTotal() { ret setFieldAndReturn(cpuTotal := percentRatioStrOneDigit((1-freeInCore())/numberOfCores())); } double freeInCore() { ret ratio(toSeconds(screenShotCountdownTotalSleepTime), elapsedSeconds(loopStarted)); } replace jSection with jCenteredSection. {} visualize { imageSurface = new IIImageSurface; setDoubleBuffered(imageSurface, true); imageSurface.setPixelated(true); imageSurface.noAlpha = true; ret northAndCenterWithMargin( withMargin(withLabel("Show", comboBoxAndButton( onSelectedItem( bindComboBoxToLiveValue(centerComboBox(autoComboBox(uiURL, cloneKeys(uiMap))), dm_fieldLiveValue uiURL()), url -> showUIURL(url) ), "Go", url -> showUIURL(url)))), mainArea = singleComponentPanel(renderUIUrl(uiURL))); } BufferedImage lastScreenImage() { ret getVar(getVar(lastScreen)); } void adjustUIForPoppedOutWindow swing { if (popDownButton == null) { Window window = cast getWindow(dm_vis()); var popBackInButton = findButton(window, "Pop Back In"); var parent = getParent(popBackInButton); print(+parent); removeFromParent(parent); // hide controls popDownButton = jPopDownButton_noText( "Pop Back In", r { dm_popInModule(me()) }, jCheckBoxMenuItem("Always On Top", isAlwaysOnTop(window), rEnter dm_toggleAlwaysOnTop), ); addControl(popDownButton); } } public bool useErrorHandling() { false; } JComponent renderUIUrl aka renderUIURL aka uiGet(S url) { var maker = uiMap.get(url); var component = callF(maker); if (component != null) ret component; ret jCenteredLabel("URL not found: " + url); } void showUIURL(S url) enter { url = trim(url); setComponent(mainArea, renderUIUrl(url)); } <A extends JComponent> A uiMapPut(S url, IF0<A> maker) { uiMap.put(url, -> maker!); ret maker!; } void uiPut(S url, IF0<JComponent> maker) { uiMap.put(url, maker); } void initUIMap { uiPut("FPS", -> jSection("FPS", dm_calculatedCenteredLabel(() -> iround(fps)))); uiPut("Screen Selector", -> { var screenSelectors = jRadioButtons( countIteratorAsList(screenCount(), i -> "Screen " + (i+1))); selectRadioButton(screenSelectors, lookAtScreen); onRadioButtonChange(screenSelectors, i -> { setField(lookAtScreen := i); }); ret jline(buttonsInGroup(screenSelectors)); }); uiPut("Screenshot with controls", -> northAndCenterWithMargin( topControls2 = /*jflowCenter*/ jPanel(new WrapLayout, flattenList2( dm_checkBox enabled(), getChildren(renderUIURL("Screen Selector")), dm_spinnerWithLabel gridRows("Rows", 1, 500), dm_checkBox("Scale down", "scaleDownPreviewImage"), dm_spinnerWithLabel previewPosterization("Posterize", 2, 256) )), jscroll_center(imageSurface))); uiPut("Enabled", -> dm_checkBox enabled()); uiPut("Home", -> hsplit(northAndCenterWithMargin( topControls = hgrid( renderUIUrl("FPS"), jSection("Compression", dm_centeredFieldLabel longTermCompressionScore()), //jSection("Probability", dm_centeredFieldLabel longTermCompressionProbability()), jSection("CPU (" + numberOfCores() + ")", dm_centeredFieldLabel cpuTotal()) ), tabs), renderUIUrl("Screenshot with controls") )); } } // end of module
Began life as a copy of #1033508
download show line numbers debug dex old transpilations
Travelled to 2 computer(s): bhatertpkbcr, mqqgnosmbjvj
No comments. add comment
Snippet ID: | #1033526 |
Snippet name: | Gazelle V, November Edition |
Eternal ID of this version: | #1033526/70 |
Text MD5: | 7e31572c1a1a6c6d683edf8c477da725 |
Transpilation MD5: | c466d7399a6a381f7245d715acbbc9c7 |
Author: | stefan |
Category: | javax / screen recognition |
Type: | JavaX source code (Dynamic Module) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2021-12-25 23:25:12 |
Source code size: | 12322 bytes / 379 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 251 / 558 |
Version history: | 69 change(s) |
Referenced in: | [show references] |