!636 !629 // standard functions !658 // image classes import java.awt.*; import java.awt.image.*; import java.util.List; import javax.imageio.*; import java.lang.reflect.*; public class main { static RGBImage originalImage; static int maxStructureSize = 1000; static abstract class Params { RGBImage originalImage; abstract RGBImage render(); abstract Params copy(); 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() { if (/*originalImage == main.originalImage &&*/ structureSize(this, Params.class) > maxStructureSize) return 1.5; return diff(originalImage, getImage()); } boolean isBetterThan(Params p) { return getScore() < p.getScore(); } } static class VSplit extends Params { double splitPoint; RGB col1, col2; VSplit copy() { VSplit p = new VSplit(); baseClone(p); p.splitPoint = splitPoint; p.col1 = col1; p.col2 = col2; return p; } public String toString() { return "VSplit " + splitPoint + " " + col1 + " " + col2; } RGBImage render() { int w = originalImage.getWidth(), h = originalImage.getHeight(); RGBImage image = new RGBImage(w, h, Color.white); vsplit(image, this); return image; } } static class Solid extends Params { RGB col; Solid copy() { Solid p = new Solid(); baseClone(p); p.col = col; return p; } public String toString() { return "Solid " + col; } RGBImage render() { int w = originalImage.getWidth(), h = originalImage.getHeight(); return new RGBImage(w, h, col); } } interface Reproducer { public Params reproduce(RGBImage original); } static class RandomVSplit implements Reproducer { int n = -1; public Params reproduce(RGBImage original) { ++n; VSplit p = new VSplit(); p.originalImage = original; p.splitPoint = random(); if (n % 2 == 0) { p.col1 = randomColor(); p.col2 = randomColor(); } else { p.col1 = probeRandomPixel(original); p.col2 = probeRandomPixel(original); } return p; } } static class RandomSolid implements Reproducer { int n = -1; public Params reproduce(RGBImage original) { ++n; Solid p = new Solid(); p.originalImage = original; if (n % 2 == 0) { p.col = randomColor(); } else { p.col = probeRandomPixel(original); } 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 = vary(best); //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; } Params vary(Params p) { if (p instanceof VSplit) { VSplit n = ((VSplit) p).copy(); int s = random(3); if (s == 0) varySplitPoint(n); else if (s == 1) n.col1 = varyColor(n.col1); else n.col2 = varyColor(n.col2); return n; } else if (p instanceof Solid) { Solid n = ((Solid) p).copy(); n.col = varyColor(n.col); return n; } else if (p instanceof Gridded) { //print "Varying Gridded" Gridded n = ((Gridded) p).copy(); int i = random(n.array.length); n.array[i] = vary(n.array[i]); return n; } return null; } void varySplitPoint(VSplit p) { p.splitPoint = Math.max(0, Math.min(1, p.splitPoint+random(-0.1, 0.1))); } float varyChannel(float x) { return Math.max(0f, Math.min(1f, (float) (x+random(-0.1, 0.1)))); } RGB varyColor(RGB rgb) { int s = random(3); if (s == 0) return new RGB(varyChannel(rgb.r), rgb.g, rgb.b); else if (s == 1) return new RGB(rgb.r, varyChannel(rgb.g), rgb.b); else return new RGB(rgb.r, rgb.g, varyChannel(rgb.b)); } } static class Alternate implements Reproducer { int n = -1; Reproducer[] list; Alternate(Reproducer... list) { this.list = list; } public Params reproduce(RGBImage original) { ++n; return list[n % list.length].reproduce(original); } } interface ReproducerMaker { public Reproducer make(); } static class Gridded extends Params { int w, h; Params[] array; Gridded(int w, int h) { this.w = w; this.h = h; array = new Params[w*h]; } Gridded copy() { Gridded p = new Gridded(w, h); baseClone(p); for (int i = 0; i < w*h; i++) p.array[i] = array[i].copy(); return p; } public String toString() { StringBuilder buf = new StringBuilder("grid{"); for (int i = 0; i < w*h; i++) { if (i != 0) buf.append(", "); buf.append(array[i]); } return buf + "}"; } public RGBImage render() { int ow = originalImage.getWidth(), oh = originalImage.getHeight(); RGBImage img = new RGBImage(ow, oh, Color.white); for (int y = 0; y < h; y++) for (int x = 0; x < w; x++) { int x1 = x*ow/w, y1 = y*oh/h; int x2 = (x+1)*ow/w, y2 = (y+1)*oh/h; RGBImage part = array[y*w+x].render(); main.copy(part, 0, 0, img, x1, y1, part.getWidth(), part.getHeight()); } return img; } } static class Grid implements Reproducer { int w, h; Reproducer[] bases; Grid(ReproducerMaker maker, int w, int h) { this.w = w; this.h = h; bases = new Reproducer[w*h]; for (int i = 0; i < w*h; i++) bases[i] = maker.make(); } RGBImage getGridElement(RGBImage originalImage, int i) { int ow = originalImage.getWidth(), oh = originalImage.getHeight(); int y = i / w; int x = i % w; int x1 = x*ow/w, y1 = y*oh/h; int x2 = (x+1)*ow/w, y2 = (y+1)*oh/h; return originalImage.clip(x1, y1, x2-x1, y2-y1); } public Params reproduce(RGBImage original) { Gridded gridded = new Gridded(w, h); gridded.originalImage = original; for (int i = 0; i < w*h; i++) { RGBImage img = getGridElement(original, i); Params p = bases[i].reproduce(img); if (p == null) return null; gridded.array[i] = p; } return gridded; } } static ReproducerMaker baseMaker = new ReproducerMaker() { public Reproducer make() { return new VaryBest( new Alternate( new RandomSolid(), new RandomVSplit() )); } }; // main reproduce function static Reproducer reproducer = new VaryBest(new Alternate( baseMaker.make(), new Grid(baseMaker, 4, 4), new Grid(baseMaker, 16, 8) )); static Params reproduce(RGBImage original, int ntry) { int w = original.getWidth(), h = original.getHeight(); return reproducer.reproduce(original); } public static void main(String[] args) { String imageID = "#1000326"; // Bryan Cranston! if (args.length != 0) imageID = args[0]; final String _imageID = imageID; JFrame frame = new JFrame("A JavaX Frame"); final ImageSurface imageSurface = new ImageSurface(); Component panel = imageSurface; frame.add(panel); frame.setBounds(100, 100, 300, 200); frame.setVisible(true); exitOnFrameClose(frame); new Thread() { public void run() { originalImage = loadImage(_imageID); originalImage = resizeToWidth(originalImage, 100); reproduceOpenEnd(originalImage, imageSurface); } }.start(); } static void reproduceOpenEnd(RGBImage original, ImageSurface imageSurface) { Params best = null; long lastPrint = 0; for (int ntry = 1; ; ntry++) { if (System.currentTimeMillis() >= lastPrint+1000) { lastPrint = System.currentTimeMillis(); if (best == null) System.out.println("Try " + ntry); else { System.out.println("Best: " + best); System.out.println("Try " + ntry + ", score: " + formatDouble(best.getScore()*100, 2) + "%, structure size: " + structureSize(best, Params.class)); } } Params p = reproduce(original, ntry); 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 RGB probeRandomPixel(RGBImage image) { int x = (int) (random()*(image.getWidth()-1)); int y = (int) (random()*(image.getHeight()-1)); return image.getPixel(x, y); } static RGB randomColor() { return new RGB(random(), random(), random()); } static RGBImage resizeToWidth(RGBImage image, int w) { return resize(image, w, (int) ((image.getHeight()*(double) w)/image.getWidth())); } public static RGBImage resize(RGBImage image, int w, int h) { if (w == image.getWidth() && h == image.getHeight()) return image; int[] pixels = new int[w*h]; for (int y = 0; y < h; y++) for (int x = 0; x < w; x++) pixels[y*w+x] = image.getInt(x*image.getWidth()/w, y*image.getHeight()/h); return new RGBImage(w, h, pixels); } static boolean useImageCache = true; static RGBImage loadImage(String snippetID) { try { File dir = new File(System.getProperty("user.home"), ".tinybrain/image-cache"); if (useImageCache) { dir.mkdirs(); File file = new File(dir, snippetID + ".png"); if (file.exists() && file.length() != 0) try { return new RGBImage(ImageIO.read(file)); } catch (Throwable e) { e.printStackTrace(); // fall back to loading from sourceforge } } String imageURL = getImageURL(parseSnippetID(snippetID)); System.err.println("Loading image: " + imageURL); BufferedImage image = ImageIO.read(new URL(imageURL)); if (useImageCache) { File tempFile = new File(dir, snippetID + ".tmp." + System.currentTimeMillis()); ImageIO.write(image, "png", tempFile); tempFile.renameTo(new File(dir, snippetID + ".png")); //Log.info("Cached image."); } //Log.info("Loaded image."); return new RGBImage(image); } catch (IOException e) { throw new RuntimeException(e); } } static String getImageURL(long snippetID) throws IOException { String url; if (snippetID == 1000010 || snippetID == 1000012) url = "http://tinybrain.de:8080/tb/show-blobimage.php?id=" + snippetID; else url = "http://eyeocr.sourceforge.net/filestore/filestore.php?cmd=serve&file=blob_" + snippetID + "&contentType=image/png"; return url; } public static long parseSnippetID(String snippetID) { return Long.parseLong(shortenSnippetID(snippetID)); } private static String shortenSnippetID(String snippetID) { if (snippetID.startsWith("#")) snippetID = snippetID.substring(1); String httpBlaBla = "http://tinybrain.de/"; if (snippetID.startsWith(httpBlaBla)) snippetID = snippetID.substring(httpBlaBla.length()); return snippetID; } static Random _random = new Random(); static double random() { return _random.nextInt(100001)/100000.0; } static int random(int max) { return _random.nextInt(max); } static double random(double min, double max) { return min+random()*(max-min); } static void vsplit(RGBImage img, VSplit p) { int w = img.getWidth(), h = img.getHeight(); for (int yy = 0; yy < h; yy++) for (int xx = 0; xx < w; xx++) { //double x = ((double) xx)/(w-1); double y = ((double) yy)/(h-1); RGB col = y <= p.splitPoint ? p.col1 : p.col2; img.setPixel(xx, yy, col); } } public static double pixelDiff(RGB a, RGB b) { return (Math.abs(a.r-b.r) + Math.abs(a.g-b.g) + Math.abs(a.b-b.b))/3; } public static double diff(RGBImage image, RGBImage image2) { int w = image.getWidth(), h = image.getHeight(); double sum = 0; for (int y = 0; y < h; y++) for (int x = 0; x < w; x++) sum += pixelDiff(image.getRGB(x, y), image2.getRGB(x, y)); return sum/(w*h); } public static void copy(RGBImage src, int srcX, int srcY, RGBImage dst, int dstX, int dstY, int w, int h) { for (int y = 0; y < h; y++) for (int x = 0; x < w; x++) dst.setPixel(dstX+x, dstY+y, src.getPixel(srcX+x, srcY+y)); } public static int structureSize(Object o, Class baseClass) { if (o == null) return 0; int size = 1; Class c = o.getClass(); if (c.isArray()) { int n = Array.getLength(o); for (int i = 0; i < n; i++) size += structureSize(Array.get(o, i), baseClass); } else while (c != Object.class && c != baseClass) { Field[] fields = c.getDeclaredFields(); for (Field field : fields) { if ((field.getModifiers() & Modifier.STATIC) != 0) continue; if (field.getType().isPrimitive()) ++size; else { Object value = null; try { value = field.get(o); } catch (IllegalAccessException e) { throw new RuntimeException(e); } size += structureSize(value, baseClass); } } c = c.getSuperclass(); } return size; } public static String formatDouble(double d, int digits) { String format = "0."; for (int i = 0; i < digits; i++) format += "#"; return new java.text.DecimalFormat(format, new java.text.DecimalFormatSymbols(Locale.ENGLISH)).format(d); } }
Began life as a copy of #666
download show line numbers debug dex old transpilations
Travelled to 14 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, qbtsjoyahagl, tslmcundralx, tvejysmllsmz, vouqrxazstgt
No comments. add comment
Snippet ID: | #667 |
Snippet name: | vsplit v7 (with structure size limit) |
Eternal ID of this version: | #667/1 |
Text MD5: | 731caa9ffc185015375cc7972840fb89 |
Author: | stefan |
Category: | |
Type: | JavaX source code |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2015-07-13 08:35:43 |
Source code size: | 15126 bytes / 525 lines |
Pitched / IR pitched: | No / Yes |
Views / Downloads: | 742 / 593 |
Referenced in: | [show references] |