1 | !include #1000522 // image helper functions |
2 | |
3 | sclass Best { |
4 | S desc; |
5 | double score; |
6 | Renderer renderer; |
7 | BWImage image; |
8 | |
9 | *() {} |
10 | *(S *desc, double *score, BWImage *image) {} |
11 | *(S *desc, double *score, Renderer *renderer, BWImage *image) {} |
12 | |
13 | int l() { ret main.l(desc); } |
14 | } |
15 | |
16 | static O rendererMaker; // optional maker function (S -> Renderer) |
17 | |
18 | sclass Reproducing { |
19 | BWImage bw; // original |
20 | ImageSurface imageSurfaceToUpdateWithBest; |
21 | new LinkedBlockingQueue<S> newProducts; |
22 | int maxQueueLength = 10; |
23 | volatile Best shortest100, best; |
24 | int pivotLength = -1; // no length punishment at start |
25 | int pivotStep = 1; |
26 | int fullGrabLength; // length of full grab for reference |
27 | O startProduction; // optional runnable that starts production |
28 | int descPrintLength = 100; |
29 | |
30 | void push(S product) { |
31 | if (product == null) ret; |
32 | while (newProducts.size() >= maxQueueLength && mayRun()) |
33 | sleep(100); |
34 | newProducts.add(product); |
35 | } |
36 | |
37 | double formula(S desc, double pixelScore) { |
38 | int lengthPunishment = pivotLength < 0 ? 0 |
39 | : max(0, l(desc)-pivotLength); |
40 | ret pixelScore-lengthPunishment; |
41 | } |
42 | |
43 | void loadShortest100() { |
44 | S shortest = shortest100(); |
45 | if (shortest != null) |
46 | shortest100 = new Best(shortest, 100, null); |
47 | } |
48 | |
49 | void reproduceOpenEnd() { |
50 | loadShortest100(); |
51 | best = null; |
52 | fullGrabLength = l(fullGrab(bw)); |
53 | long lastPrint = 0, lastN = 0; |
54 | for (long ntry = 1; ; ntry++) { |
55 | ping(); |
56 | long now = now(); |
57 | if (now >= lastPrint+1000) { |
58 | long tps = (ntry-lastN)*1000/(now-lastPrint); |
59 | lastPrint = now; |
60 | lastN = ntry; |
61 | String s = "Try " + ntry + " (" + tps + "/s)"; |
62 | if (best == null) |
63 | print(s); |
64 | else { |
65 | print("Best: " + shorten(best.desc, descPrintLength)); |
66 | print(s + ", score: " + formatDouble(best.score, 2) + "%, l=" + l(best.desc) + ", pivotL=" + pivotLength + "/" + fullGrabLength + (shortest100 == null ? "" : ", shortest100=" + shortest100.l())); |
67 | } |
68 | } |
69 | S desc; |
70 | try { |
71 | desc = grabFromQueue(newProducts); |
72 | } catch e { |
73 | print("Production failed: " + exceptionToStringShort(e)); |
74 | continue; |
75 | } |
76 | Renderer p; |
77 | try { |
78 | p = makeRenderer(desc); |
79 | } catch { |
80 | print("Can't unstructure: " + desc); |
81 | continue; |
82 | } |
83 | |
84 | BWImage rendering = render(p, bw); |
85 | double pixelScore = 100*(1-diff(bw, rendering)); |
86 | double score = formula(desc, pixelScore); |
87 | |
88 | if (best == null || p != null && score > getScore(best)) { |
89 | //System.out.println("New best! " + score); |
90 | best = new Best(desc, score, p, rendering); |
91 | if (pixelScore >= 100 && (shortest100 == null || shortest100.l() > l(desc))) { |
92 | shortest100 = new Best(desc, pixelScore, rendering); |
93 | saveTextFile(getProgramFile("shortest100.txt"), bw.getWidth() + " " + bw.getHeight() + " " + desc); |
94 | } |
95 | imageSurfaceToUpdateWithBest.setImage(best.image.getBufferedImage()); |
96 | } |
97 | |
98 | if (solved()) { |
99 | print("Solved! l=" + best.l()); |
100 | print(shorten(best.desc, descPrintLength)); |
101 | break; |
102 | } |
103 | } |
104 | } |
105 | |
106 | bool solved() { |
107 | ret getScore(best) >= 100.0; |
108 | } |
109 | |
110 | S bestDesc() { |
111 | ret getDesc(best); |
112 | } |
113 | |
114 | BufferedImage descToImage(S desc) { |
115 | try { |
116 | ret makeRenderer(desc).render(bw.getWidth(), bw.getHeight()).getBufferedImage(); |
117 | } catch { |
118 | fail(desc); |
119 | } |
120 | } |
121 | |
122 | void produce() { |
123 | callF(startProduction); |
124 | } |
125 | |
126 | void findShortest100_openEnd() { |
127 | produce(); |
128 | reproduceOpenEnd(); |
129 | |
130 | while (solved()) { |
131 | pivotLength = best.l() - pivotStep; |
132 | print("Trying pivot length " + pivotLength); |
133 | |
134 | produce(); |
135 | reproduceOpenEnd(); |
136 | } |
137 | } |
138 | } |
139 | |
140 | static class FullGrab extends Renderer { |
141 | int dw, dh; |
142 | byte[] data; |
143 | |
144 | BWImage render(int w, int h) { |
145 | if (w != dw || h != dh) |
146 | fail("size: \*w*/ \*h*/ \*dw*/ \*dh*/"); |
147 | ret new BWImage(w, h, data); |
148 | } |
149 | } |
150 | |
151 | static class HRepeat extends Renderer { |
152 | int width; |
153 | S inner; |
154 | |
155 | BWImage render(int w, int h) { |
156 | BWImage img = new BWImage(w, h); |
157 | BWImage clip = ((Renderer) unstructure(inner)).render(width, h); |
158 | for (int x = 0; x < w; x += width) |
159 | copy(clip, 0, 0, img, x, 0, width, h); |
160 | ret img; |
161 | } |
162 | } |
163 | |
164 | static S fullGrab(BWImage img) { |
165 | DynamicObject d = new DynamicObject("FullGrab"); |
166 | int w = img.getWidth(), h = img.getHeight(); |
167 | d.put("dw", w); |
168 | d.put("dh", h); |
169 | byte[] data = new byte[w*h]; |
170 | for (int y = 0; y < h; y++) |
171 | for (int x = 0; x < w; x++) |
172 | data[y*w+x] = img.getByte(x, y); |
173 | d.put("data", data); |
174 | ret structure(d); |
175 | } |
176 | |
177 | static S hrepeat(BWImage img, int width) { |
178 | int h = img.getHeight(); |
179 | BWImage clip = img.clip(0, 0, width, h); |
180 | ret structure(dynamicObject("HRepeat", "width", width, "inner", fullGrab(clip))); |
181 | } |
182 | |
183 | static S varyFloat(S s) { |
184 | L<S> tok = javaTok(s); |
185 | int i = tok.indexOf("f"); |
186 | if (i < 0) null; |
187 | float f = Float.parseFloat(unquote(tok.get(i+2))); |
188 | f = (float) (f+random(-0.1, 0.1)); |
189 | tok.set(i+2, quote(str(f))); |
190 | ret join(tok); |
191 | } |
192 | |
193 | static BWImage render(Renderer p, BWImage original) { |
194 | ret p.render(original.getWidth(), original.getHeight()); |
195 | } |
196 | |
197 | static interface Reproducer { |
198 | public S reproduce(BWImage original); |
199 | } |
200 | |
201 | static class Solid extends Renderer { |
202 | float col; |
203 | |
204 | BWImage render(int w, int h) { |
205 | ret new BWImage(w, h, col); |
206 | } |
207 | } |
208 | |
209 | static class RandomSolid implements Reproducer { |
210 | int n = -1; |
211 | public S reproduce(BWImage original) { |
212 | ++n; |
213 | DynamicObject p = new DynamicObject("Solid"); |
214 | if (n % 2 == 0) { |
215 | p.put("col", randomBrightness()); |
216 | } else { |
217 | p.put("col", probeRandomPixel(original)); |
218 | } |
219 | ret structure(p); |
220 | } |
221 | } |
222 | |
223 | static abstract class Renderer { |
224 | abstract BWImage render(int w, int h); |
225 | } |
226 | |
227 | static S shortest100() { |
228 | ret loadTextFile(getProgramFile("shortest100.txt")); |
229 | } |
230 | |
231 | static BufferedImage renderShortest100() { |
232 | ret render(shortest100()); |
233 | } |
234 | |
235 | static double getScore(Best b) { |
236 | ret b == null ? 0 : b.score; |
237 | } |
238 | |
239 | static S getDesc(Best b) { |
240 | ret b == null ? null : b.desc; |
241 | } |
242 | |
243 | static Renderer makeRenderer(S desc) { |
244 | if (rendererMaker != null) { |
245 | Renderer r = cast callF(rendererMaker, desc); |
246 | if (r != null) ret r; |
247 | } |
248 | ret (Renderer) unstructure(desc); |
249 | } |
250 | |
251 | static BufferedImage render(S fullDesc) { |
252 | if (fullDesc == null) null; |
253 | new Matches m; |
254 | assertTrue(jmatchStart("* *", fullDesc, m)); |
255 | int w = m.psi(0), h = m.psi(1); |
256 | S desc = m.unq(2); |
257 | ret makeRenderer(desc).render(w, h).getBufferedImage(); |
258 | } |
Began life as a copy of #1004551
download show line numbers debug dex old transpilations
Travelled to 13 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt
No comments. add comment
Snippet ID: | #1004556 |
Snippet name: | class "Reproducing" (image reproduction framework) + FullGrab etc. |
Eternal ID of this version: | #1004556/1 |
Text MD5: | 4c8235723ff6b8de1a3288f59805c5c8 |
Author: | stefan |
Category: | javax / a.i. |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2016-08-22 16:29:57 |
Source code size: | 6802 bytes / 258 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 631 / 1006 |
Referenced in: | [show references] |