Uses 1113K of libraries. Click here for Pure Java version (24075L/129K).
1 | !7 |
2 | |
3 | cm GazelleV > DynPrintLogAndEnabled { |
4 | switchable int x1; |
5 | switchable int y1; |
6 | switchable int w = screenWidth(); |
7 | switchable int h = screenHeight(); |
8 | switchable double maxFPS = 10; |
9 | switchable int previewWidth = 200; |
10 | switchable double statsEvery = 5; |
11 | switchable volatile bool brokenMethod; |
12 | |
13 | PersistableThrowable lastProcessingError; |
14 | transient WithTimestamp<OKOrError<BufferedImage>> lastScreen; |
15 | transient new Average screenShotTime; |
16 | transient new Average iiTime; |
17 | transient Timestamp loopStarted; |
18 | transient new RestartableCountdown screenShotCountdown; |
19 | transient ImageSurface imageSurface; |
20 | transient Throwable currentProcessingError; |
21 | transient BufferedImage previewImage; |
22 | transient JButton popDownButton; |
23 | transient JComponent topControls; |
24 | transient long screenShotsTaken; |
25 | transient double fps; |
26 | transient Compression longTermCompression; |
27 | transient S longTermCompressionProbability; |
28 | transient S longTermCompressionScore; |
29 | |
30 | Rect area() { ret rect(x1, y1, w, h); } |
31 | |
32 | class Compression { |
33 | settable BufferedImage image; |
34 | settable BWIntegralImage ii; |
35 | CompressionSearch_AnyType search; |
36 | int baseLineLength; // length of trivial compression |
37 | GridCodec1 codec; |
38 | double compressionPercentage; |
39 | |
40 | S score() { |
41 | var submission = search?.bestSubmission(); |
42 | Int compressedSize = or(submission.compressedSize(), baseLineLength); |
43 | compressionPercentage = doubleRatio(compressedSize, baseLineLength)*100; |
44 | ret formatDouble(compressionPercentage, 3) + "%"; |
45 | } |
46 | |
47 | IProbabilisticScheduler scheduler() { |
48 | ret search?.scheduler(); |
49 | } |
50 | |
51 | S probability() { |
52 | var scheduler = scheduler(); |
53 | if (scheduler == null) ret "-"; |
54 | var prob = scheduler.lastExecutedProbability(); |
55 | ret formatDouble(prob, 3); |
56 | } |
57 | |
58 | run { |
59 | int lHex = pixelCount(image)*8; |
60 | baseLineLength = calculateLengthOfFunctionCall imageFromHex(lHex+2); |
61 | print(+baseLineLength); |
62 | |
63 | codec = new GridCodec1(image); |
64 | search = codec.forward(); |
65 | //showImage(codec.renderCellsLinearly()); |
66 | |
67 | thread "Gazelle Visual" { |
68 | repeat 60 { |
69 | stepForNSeconds(1, search); |
70 | print(stepCount := search.scheduler().stepCount()); |
71 | setFields( |
72 | longTermCompressionProbability := probability(), |
73 | longTermCompressionScore := score()); |
74 | } |
75 | |
76 | try { |
77 | L<IJavaExpr> cellCompressions = codec.strat.codeForElements(); |
78 | //showText("Compression", lines(map shorten_str(cellCompressions))); |
79 | |
80 | S code = str(codec.winnerCode()); |
81 | S name = "Screenshot " + ymdMinusHMS(); |
82 | File f = makeFileNameUnique_beforeExtension( |
83 | javaxDataDir("Compressed Screenshots/" + name + ".javax")); |
84 | saveTextFile(f, code); |
85 | printFileInfo(f); |
86 | saveGZTextFile(f = replaceExtension(f, ".jgz"), code); |
87 | printFileInfo(f); |
88 | |
89 | /* |
90 | print("Evaling " + nChars(code)); |
91 | //LL<Int> lol = cast dm_javaEval(code); |
92 | BufferedImage restored = cast dm_javaEval(code); |
93 | assertImagesIdentical(restored, image); |
94 | print("Image restored!"); |
95 | |
96 | dm_showImage("Restored from " + nChars(code), restored); |
97 | */ |
98 | } catch e { printStackTrace(e); } |
99 | } |
100 | } |
101 | } |
102 | |
103 | start-thread { |
104 | dm_registerAs_direct gazelleV(); |
105 | dm_watchField enabled(r { if (enabled) dm_reload(); }); |
106 | |
107 | // TODO: react to event sent by OS |
108 | dm_doEvery(1.0, r { |
109 | if (dm_moduleIsPoppedOut()) adjustUIForPoppedOutWindow(); |
110 | }); |
111 | |
112 | print("Screen bounds: " + allScreenBounds()); |
113 | |
114 | dm_doEvery(min(statsEvery, 10.0), statsEvery, r { if (enabled) printStats(); }); |
115 | |
116 | loopStarted = tsNow(); |
117 | shoot(); |
118 | } |
119 | |
120 | void shoot enter { |
121 | if (!enabled) ret; |
122 | |
123 | long targetTime = sysNow()+iround(1000/maxFPS); |
124 | long time = nanoTime(); |
125 | |
126 | try { |
127 | lastScreen = withTimestamp(okOrError(-> screenshot(area()))); |
128 | ++screenShotsTaken; |
129 | setField(fps := doubleRatio(screenShotsTaken, elapsedSeconds(loopStarted))); |
130 | screenShotTime.add(nanosToSeconds(nanoTime()-time)); |
131 | if (lastScreen->isOK()) { |
132 | time = nanoTime(); |
133 | var ii = BWIntegralImage(lastScreen!!); |
134 | //var ii = BWIntegralImage_luminosity(lastScreen!!); |
135 | iiTime.add(nanosToSeconds(nanoTime()-time)); |
136 | |
137 | if (longTermCompression == null) { |
138 | longTermCompression = new Compression() |
139 | .image(lastScreen!!) |
140 | .ii(ii); |
141 | longTermCompression.run(); |
142 | } |
143 | |
144 | previewImage = |
145 | // FAST BUT BROKEN!! |
146 | brokenMethod ? scaledBufferedImageFromBWIntegralImage(ii, previewWidth) |
147 | : scaleDownUsingIntegralImageBW(ii, previewWidth).getBufferedImage(); |
148 | imageSurface?.setImage(previewImage); |
149 | |
150 | cpuTotal(); |
151 | } |
152 | |
153 | currentProcessingError = null; |
154 | } catch print e { |
155 | setField(lastProcessingError := currentProcessingError = e); |
156 | sleepSeconds(60); // errors in processing are no good |
157 | } |
158 | |
159 | screenShotCountdown.setTargetTime(targetTime, r shoot); |
160 | } |
161 | |
162 | void printStats() { print(stats()); } |
163 | |
164 | S stats() { |
165 | var screen = lastScreen?!; |
166 | ret formatColonProperties_noNulls( |
167 | "Monitored area", area(), |
168 | "Error", screen?.getError(), |
169 | "Last screenshot taken", lastScreen?.timeStamp(), |
170 | "Average time to take a screenshot", screenShotTime, |
171 | "Average time to make integral image", iiTime, |
172 | "Capacity left in first core", percentRatioStrOneDigit(freeInCore()), |
173 | "Total CPU used", cpuTotal(), |
174 | ); |
175 | } |
176 | |
177 | S cpuTotal() { |
178 | ret setFieldAndReturn(cpuTotal := percentRatioStrOneDigit((1-freeInCore())/numberOfCores())); |
179 | } |
180 | |
181 | double freeInCore() { |
182 | ret ratio(toSeconds(screenShotCountdown.totalSleepTime), |
183 | elapsedSeconds(loopStarted)); |
184 | } |
185 | |
186 | replace jSection with jCenteredSection. |
187 | {} |
188 | visual |
189 | hsplit(northAndCenterWithMargin( |
190 | topControls = hgrid( |
191 | jSection("FPS", dm_calculatedCenteredLabel(() -> iround(fps))), |
192 | jSection("Compression", dm_centeredFieldLabel longTermCompressionScore()), |
193 | jSection("Probability", dm_centeredFieldLabel longTermCompressionProbability()), |
194 | jSection("CPU (" + numberOfCores() + ")", dm_centeredFieldLabel cpuTotal()) |
195 | ), |
196 | super /* print log */), |
197 | jscroll_center(imageSurface = doubleBufferedImageSurface_noAlpha())); |
198 | |
199 | BufferedImage lastScreenImage() { ret getVar(getVar(lastScreen)); } |
200 | |
201 | void adjustUIForPoppedOutWindow swing { |
202 | if (popDownButton == null) { |
203 | Window window = cast getWindow(dm_vis()); |
204 | |
205 | var popBackInButton = findButton(window, "Pop Back In"); |
206 | var parent = getParent(popBackInButton); |
207 | print(+parent); |
208 | |
209 | removeFromParent(parent); // hide controls |
210 | |
211 | popDownButton = jPopDownButton_noText( |
212 | "Pop Back In", r { dm_popInModule(me()) }, |
213 | jCheckBoxMenuItem("Always On Top", isAlwaysOnTop(window), |
214 | rEnter dm_toggleAlwaysOnTop), |
215 | ); |
216 | addControl(popDownButton); |
217 | } |
218 | } |
219 | } |
Began life as a copy of #1033298
download show line numbers debug dex old transpilations
Travelled to 3 computer(s): bhatertpkbcr, mowyntqkapby, mqqgnosmbjvj
No comments. add comment
Snippet ID: | #1033309 |
Snippet name: | Gazelle V, New UI [HEAD] |
Eternal ID of this version: | #1033309/71 |
Text MD5: | e71398d1cc9e39e9a5dfdd2b3728de2a |
Transpilation MD5: | aed26719c25275e8488ed8d04259585a |
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-10-28 19:38:43 |
Source code size: | 7285 bytes / 219 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 204 / 992 |
Version history: | 70 change(s) |
Referenced in: | [show references] |