Libraryless. Click here for Pure Java version (8633L/57K/207K).
!7 !include #1000522 // helper functions static RGBImage originalImage; static int imageWidth = 200; // XXX - main reproduce function static Reproducer reproducer = new Layers( new RandomSolid()) .add(2, RandomBox.class) .varyBest; static abstract class Base { abstract Base copy(); abstract void vary(); Base copyVary() { Base copy = copy(); copy.vary(); return copy; } } static abstract class Overlay extends Base { abstract Overlay copy(); abstract void renderOn(RGBImage image); } // Params must be immutable! static abstract class Params extends Base { RGBImage originalImage; abstract Params copy(); abstract RGBImage render(); void baseClone(Params p) { p.originalImage = originalImage; } RGBImage rendered; RGBImage getImage() { if (rendered == null) rendered = render(); return rendered; } double score = 2.0; double getScore() { if (score == 2.0) score = calcScore(); return score; } double calcScore() { return diff(originalImage, getImage()); } boolean isBetterThan(Params p) { return getScore() < p.getScore(); } } static class Box extends Overlay { double cx, cy, w, h; RGB color; Box copy() { Box p = new Box(); p.cx = cx; p.cy = cy; p.w = w; p.h = h; p.color = color; return p; } public String toString() { return "Box " + cx + " " + cy + " " + w + " " + h + " " + color; } void renderOn(RGBImage image) { box(image, this); } void vary() { int s = random(5); if (s == 0) cx = vary01(cx); else if (s == 1) cy = vary01(cy); else if (s == 2) w = vary01(w); else if (s == 3) h = vary01(h); else color = varyColor(color); } } static class Solid extends Overlay { RGB col; Solid copy() { Solid p = new Solid(); p.col = col; return p; } public String toString() { return "Solid " + col; } void renderOn(RGBImage image) { int w = image.getWidth(), h = image.getHeight(); for (int y = 0; y < h; y++) for (int x = 0; x < w; x++) image.setPixel(x, y, col); } void vary() { col = varyColor(col); } } interface Reproducer { public Params reproduce(RGBImage original); } interface OverlayReproducer { public Overlay reproduce(RGBImage original); } static class RandomBox implements OverlayReproducer { int n = -1; public Overlay reproduce(RGBImage original) { ++n; new Box p; p.cx = random(); p.cy = random(); p.w = random()*0.1; p.h = random()*0.1; if (n % 2 == 0) p.color = randomColor(); else p.color = probeRandomPixel(original); return p; } } static class RandomSolid implements OverlayReproducer { int n = -1; public Overlay reproduce(RGBImage original) { ++n; Solid p = new Solid(); if (n % 2 == 0) { p.col = randomColor(); } else { p.col = probeRandomPixel(original); } return p; } } static class WhiteSolid implements OverlayReproducer { public Overlay reproduce(RGBImage original) { Solid p = new Solid(); p.col = new RGB(Color.white); return p; } } static class VaryBest implements Reproducer { Reproducer base; Params best; VaryBest(Reproducer base) { this.base = base; } public Params reproduce(RGBImage original) { Params p = base.reproduce(original); if (best == null || p.isBetterThan(best)) best = p; Params variation = (Params) best.copyVary(); //System.out.println("Best: " + best.getScore() + ", variation: " + variation.getScore()); if (variation.isBetterThan(best)) { //System.out.println("Using variation, diff=" + (best.getScore()-variation.getScore())); best = variation; } return best; } void reset() { best = null; } } static class Layered extends Params { Layers myMaker; Overlay[] list; Layered(Layers myMaker, Overlay[] list) { this.myMaker = myMaker; this.list = list; } Layered copy() { Layered p = new Layered(myMaker, new Overlay[list.length]); baseClone(p); for (int i = 0; i < list.length; i++) p.list[i] = (Overlay) list[i].copy(); return p; } public String toString() { StringBuilder buf = new StringBuilder("layered{"); for (int i = 0; i < list.length; i++) { if (i != 0) buf.append(", "); buf.append(list[i]); } return buf + "}"; } RGBImage render() { RGBImage image = new RGBImage(originalImage.getWidth(), originalImage.getHeight(), Color.white); for (int i = 0; i < list.length; i++) list[i].renderOn(image); return image; } void vary() { int i = random(list.length); if (random(2) == 0) { //System.out.println("Varying layer " + i); list[i] = (Overlay) list[i].copyVary(); } else { //double score = getScore(); OverlayReproducer maker = myMaker.list[i]; list[i] = maker.reproduce(originalImage); //System.out.println("Exchanging layer " + i + " from " + maker + ", improvement: " + (score-getFreshScore())); } } } static class Layers implements Reproducer { OverlayReproducer[] list; long ntry = -1; int stepTime = 0/*500*/; VaryBest varyBest = new VaryBest(this); Layers(OverlayReproducer... list) { this.list = list; } Layers add(int n, Class<? extends OverlayReproducer> xClass) ctex { OverlayReproducer l[] = new OverlayReproducer[list.length+n]; System.arraycopy(list, 0, l, 0, list.length); for (int i = 0; i < n; i++) l[list.length+i] = xClass.newInstance(); list = l; return this; } public Params reproduce(RGBImage original) { ++ntry; int n = this.list.length; if (stepTime != 0) { // build up image gradually to optimize lower layers first n = (int) Math.min(n, ntry/stepTime+1); varyBest.reset(); } Overlay[] list = new Overlay[n]; for (int i = 0; i < n; i++) list[i] = this.list[i].reproduce(original); Layered result = new Layered(this, list); result.originalImage = original; return result; } } static Params reproduce(RGBImage original) { int w = original.getWidth(), h = original.getHeight(); return reproducer.reproduce(original); } psvm { String imageID = "#1000332"; // Picture of two coins for (int i = 0; i < args.length; i++) { String arg = args[i]; if (arg.equals("width")) imageWidth = Integer.parseInt(args[++i]); else if (isSnippetID(arg)) imageID = arg; } final String _imageID = imageID; JFrame frame = new JFrame("A JavaX Frame"); JPanel grid = new JPanel(new GridLayout(2, 1)); final ImageSurface imageSurface = new ImageSurface(); final ImageSurface original = new ImageSurface(); grid.add(imageSurface); grid.add(original); frame.add(grid); frame.setBounds(100, 100, 100+imageWidth+20, 300); frame.setVisible(true); exitOnFrameClose(frame); new Thread() { public void run() { originalImage = loadImage(_imageID); originalImage = resizeToWidth(originalImage, imageWidth); original.setImage(originalImage); reproduceOpenEnd(originalImage, imageSurface); } }.start(); } static void reproduceOpenEnd(RGBImage original, ImageSurface imageSurface) { Params best = null; long lastPrint = 0, lastN = 0; for (long ntry = 1; ; ntry++) { long now = System.currentTimeMillis(); if (now >= lastPrint+1000) { long tps = (ntry-lastN)*1000/(now-lastPrint); lastPrint = now; lastN = ntry; String s = "Try " + ntry + " (" + tps + "/s)"; if (best == null) System.out.println(s); else { System.out.println("Best: " + best); System.out.println(s + ", score: " + formatDouble(best.getScore()*100, 2) + "%, structure size: " + structureSize(best, Params.class)); } } Params p = reproduce(original); if (best == null || p != null && p.getScore() < best.getScore()) { //System.out.println("New best! " + p.getScore()); best = p; imageSurface.setImage(p.getImage()); } if (p != null && p.getScore() == 0.0) break; } } static void box(RGBImage img, Box p) { int w = img.getWidth(), h = img.getHeight(); double x1 = normalize(p.cx-p.w), x2 = normalize(p.cx+p.w); double y1 = normalize(p.cy-p.h), y2 = normalize(p.cy+p.h); int xx1 = round(x1*(w-1)), xx2 = round(x2*(w-1)); int yy1 = round(y1*(h-1)), yy2 = round(y2*(h-1)); for (int yy = yy1; yy <= yy2; yy++) for (int xx = xx1; xx <= xx2; xx++) img.setPixel(xx, yy, p.color); }
Began life as a copy of #671
download show line numbers debug dex old transpilations
Travelled to 15 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, onxytkatvevr, pyentgdyhuwx, pzhvpgtvlbxg, teubizvjbppd, tslmcundralx, tvejysmllsmz, vouqrxazstgt
No comments. add comment
Snippet ID: | #724 |
Snippet name: | Reproducing with boxes |
Eternal ID of this version: | #724/2 |
Text MD5: | 1956f845025d299caeeff78cf968c0f4 |
Transpilation MD5: | 4bf9f0b903b28d9af03f523d00816e8c |
Author: | stefan |
Category: | |
Type: | JavaX source code |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2018-05-06 16:26:21 |
Source code size: | 9043 bytes / 367 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 674 / 735 |
Version history: | 1 change(s) |
Referenced in: | [show references] |