Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

525
LINES

< > BotCompany Repo | #667 // vsplit v7 (with structure size limit)

JavaX source code - run with: x30.jar

1  
!636
2  
!629 // standard functions
3  
!658 // image classes
4  
5  
import java.awt.*;
6  
import java.awt.image.*;
7  
import java.util.List;
8  
import javax.imageio.*;
9  
import java.lang.reflect.*;
10  
11  
public class main {
12  
  static RGBImage originalImage;
13  
  static int maxStructureSize = 1000;
14  
  
15  
  static abstract class Params {
16  
    RGBImage originalImage;
17  
    abstract RGBImage render();
18  
    abstract Params copy();
19  
    
20  
    void baseClone(Params p) {
21  
      p.originalImage = originalImage;
22  
    }
23  
    
24  
    RGBImage rendered;
25  
    RGBImage getImage() {
26  
      if (rendered == null)
27  
        rendered = render();
28  
      return rendered;
29  
    }
30  
    
31  
    double score = 2.0;
32  
    double getScore() {
33  
      if (score == 2.0)
34  
        score = calcScore();
35  
      return score;
36  
    }
37  
    
38  
    double calcScore() {
39  
      if (/*originalImage == main.originalImage
40  
        &&*/ structureSize(this, Params.class) > maxStructureSize)
41  
        return 1.5;
42  
      return diff(originalImage, getImage());
43  
    }
44  
    
45  
    boolean isBetterThan(Params p) {
46  
      return getScore() < p.getScore();
47  
    }
48  
  }
49  
  
50  
  static class VSplit extends Params {
51  
    double splitPoint;
52  
    RGB col1, col2;
53  
    
54  
    VSplit copy() {
55  
      VSplit p = new VSplit();
56  
      baseClone(p);
57  
      p.splitPoint = splitPoint;
58  
      p.col1 = col1;
59  
      p.col2 = col2;
60  
      return p;
61  
    }
62  
    
63  
    public String toString() {
64  
      return "VSplit " + splitPoint + " " + col1 + " " + col2;
65  
    }
66  
67  
    RGBImage render() {
68  
      int w = originalImage.getWidth(), h = originalImage.getHeight();
69  
      RGBImage image = new RGBImage(w, h, Color.white);
70  
      vsplit(image, this);
71  
      return image;
72  
    }
73  
  }
74  
  
75  
  static class Solid extends Params {
76  
    RGB col;
77  
    
78  
    Solid copy() {
79  
      Solid p = new Solid();
80  
      baseClone(p);
81  
      p.col = col;
82  
      return p;
83  
    }
84  
    
85  
    public String toString() {
86  
      return "Solid " + col;
87  
    }
88  
89  
    RGBImage render() {
90  
      int w = originalImage.getWidth(), h = originalImage.getHeight();
91  
      return new RGBImage(w, h, col);
92  
    }
93  
  }
94  
  
95  
  interface Reproducer {
96  
    public Params reproduce(RGBImage original);
97  
  }
98  
  
99  
  static class RandomVSplit implements Reproducer {
100  
    int n = -1;
101  
    public Params reproduce(RGBImage original) {
102  
      ++n;
103  
      VSplit p = new VSplit();
104  
      p.originalImage = original;
105  
      p.splitPoint = random();
106  
      if (n % 2 == 0) {
107  
        p.col1 = randomColor();
108  
        p.col2 = randomColor();
109  
      } else {
110  
        p.col1 = probeRandomPixel(original);
111  
        p.col2 = probeRandomPixel(original);
112  
      }
113  
      return p;
114  
    }
115  
  }
116  
  
117  
  static class RandomSolid implements Reproducer {
118  
    int n = -1;
119  
    public Params reproduce(RGBImage original) {
120  
      ++n;
121  
      Solid p = new Solid();
122  
      p.originalImage = original;
123  
      if (n % 2 == 0) {
124  
        p.col = randomColor();
125  
      } else {
126  
        p.col = probeRandomPixel(original);
127  
      }
128  
      return p;
129  
    }
130  
  }
131  
  
132  
  static class VaryBest implements Reproducer {
133  
    Reproducer base;
134  
    Params best;
135  
    
136  
    VaryBest(Reproducer base) {
137  
      this.base = base;
138  
    }
139  
    
140  
    public Params reproduce(RGBImage original) {
141  
      Params p = base.reproduce(original);
142  
      if (best == null || p.isBetterThan(best))
143  
        best = p;
144  
      Params variation = vary(best);
145  
      //System.out.println("Best: " + best.getScore() + ", variation: " + variation.getScore());
146  
      if (variation.isBetterThan(best)) {
147  
        //System.out.println("Using variation, diff=" + (best.getScore()-variation.getScore()));
148  
        best = variation;
149  
      }
150  
      return best;
151  
    }
152  
    
153  
    Params vary(Params p) {
154  
      if (p instanceof VSplit) {
155  
        VSplit n = ((VSplit) p).copy();
156  
        int s = random(3);
157  
        if (s == 0)
158  
          varySplitPoint(n);
159  
        else if (s == 1)
160  
          n.col1 = varyColor(n.col1);
161  
        else
162  
          n.col2 = varyColor(n.col2);
163  
        return n;
164  
      } else if (p instanceof Solid) {
165  
        Solid n = ((Solid) p).copy();
166  
        n.col = varyColor(n.col);
167  
        return n;
168  
      } else if (p instanceof Gridded) {
169  
        //print "Varying Gridded"
170  
        Gridded n = ((Gridded) p).copy();
171  
        int i = random(n.array.length);
172  
        n.array[i] = vary(n.array[i]);
173  
        return n;
174  
      }
175  
      return null;
176  
    }
177  
    
178  
    void varySplitPoint(VSplit p) {
179  
      p.splitPoint = Math.max(0, Math.min(1, p.splitPoint+random(-0.1, 0.1)));
180  
    }
181  
    
182  
    float varyChannel(float x) {
183  
      return Math.max(0f, Math.min(1f, (float) (x+random(-0.1, 0.1))));
184  
    }
185  
    
186  
    RGB varyColor(RGB rgb) {
187  
      int s = random(3);
188  
      if (s == 0)
189  
        return new RGB(varyChannel(rgb.r), rgb.g, rgb.b);
190  
      else if (s == 1)
191  
        return new RGB(rgb.r, varyChannel(rgb.g), rgb.b);
192  
      else
193  
        return new RGB(rgb.r, rgb.g, varyChannel(rgb.b));
194  
    }
195  
  }
196  
197  
  static class Alternate implements Reproducer {
198  
    int n = -1;
199  
    Reproducer[] list;
200  
    
201  
    Alternate(Reproducer... list) {
202  
      this.list = list;
203  
    }
204  
    
205  
    public Params reproduce(RGBImage original) {
206  
      ++n;
207  
      return list[n % list.length].reproduce(original);
208  
    }
209  
  }
210  
  
211  
  interface ReproducerMaker {
212  
    public Reproducer make();
213  
  }
214  
  
215  
  static class Gridded extends Params {
216  
    int w, h;
217  
    Params[] array;
218  
    
219  
    Gridded(int w, int h) {
220  
      this.w = w;
221  
      this.h = h;
222  
      array = new Params[w*h];
223  
    }
224  
    
225  
    Gridded copy() {
226  
      Gridded p = new Gridded(w, h);
227  
      baseClone(p);
228  
      for (int i = 0; i < w*h; i++)
229  
        p.array[i] = array[i].copy();
230  
      return p;
231  
    }
232  
    
233  
    public String toString() {
234  
      StringBuilder buf = new StringBuilder("grid{");
235  
      for (int i = 0; i < w*h; i++) {
236  
        if (i != 0)
237  
          buf.append(", ");
238  
        buf.append(array[i]);
239  
      }
240  
      return buf + "}";
241  
    }
242  
    
243  
    public RGBImage render() {
244  
      int ow = originalImage.getWidth(), oh = originalImage.getHeight();
245  
      RGBImage img = new RGBImage(ow, oh, Color.white);
246  
      for (int y = 0; y < h; y++)
247  
        for (int x = 0; x < w; x++) {
248  
          int x1 = x*ow/w, y1 = y*oh/h;
249  
          int x2 = (x+1)*ow/w, y2 = (y+1)*oh/h;
250  
          RGBImage part = array[y*w+x].render();
251  
          main.copy(part, 0, 0, img, x1, y1, part.getWidth(), part.getHeight());
252  
        }
253  
      return img;
254  
    }
255  
  }
256  
  
257  
  static class Grid implements Reproducer {
258  
    int w, h;
259  
    Reproducer[] bases;
260  
    
261  
    Grid(ReproducerMaker maker, int w, int h) {
262  
      this.w = w;
263  
      this.h = h;
264  
      bases = new Reproducer[w*h];
265  
      for (int i = 0; i < w*h; i++)
266  
        bases[i] = maker.make();
267  
    }
268  
    
269  
    RGBImage getGridElement(RGBImage originalImage, int i) {
270  
      int ow = originalImage.getWidth(), oh = originalImage.getHeight();
271  
      int y = i / w;
272  
      int x = i % w;
273  
      int x1 = x*ow/w, y1 = y*oh/h;
274  
      int x2 = (x+1)*ow/w, y2 = (y+1)*oh/h;
275  
      return originalImage.clip(x1, y1, x2-x1, y2-y1);
276  
    }
277  
      
278  
    public Params reproduce(RGBImage original) {
279  
      Gridded gridded = new Gridded(w, h);
280  
      gridded.originalImage = original;
281  
      for (int i = 0; i < w*h; i++) {
282  
        RGBImage img = getGridElement(original, i);
283  
        Params p = bases[i].reproduce(img);
284  
        if (p == null)
285  
          return null;
286  
        gridded.array[i] = p;
287  
      }
288  
      return gridded;
289  
    }
290  
  }
291  
  
292  
  static ReproducerMaker baseMaker = new ReproducerMaker() {
293  
    public Reproducer make() {
294  
      return new VaryBest(
295  
        new Alternate(
296  
          new RandomSolid(), new RandomVSplit()
297  
        ));
298  
    }
299  
  };
300  
    
301  
  // main reproduce function
302  
  static Reproducer reproducer =
303  
    new VaryBest(new Alternate(
304  
      baseMaker.make(),
305  
      new Grid(baseMaker, 4, 4),
306  
      new Grid(baseMaker, 16, 8)
307  
    ));
308  
  
309  
  static Params reproduce(RGBImage original, int ntry) {
310  
    int w = original.getWidth(), h = original.getHeight();
311  
    return reproducer.reproduce(original);
312  
  }
313  
  
314  
  public static void main(String[] args) {
315  
    String imageID = "#1000326"; // Bryan Cranston!
316  
    if (args.length != 0) imageID = args[0];
317  
    final String _imageID = imageID;
318  
    
319  
    JFrame frame = new JFrame("A JavaX Frame");
320  
    
321  
    final ImageSurface imageSurface = new ImageSurface();
322  
    Component panel = imageSurface;
323  
    
324  
    frame.add(panel);
325  
    frame.setBounds(100, 100, 300, 200);
326  
    frame.setVisible(true);
327  
    exitOnFrameClose(frame);
328  
    
329  
    new Thread() {
330  
      public void run() {
331  
        originalImage = loadImage(_imageID);
332  
        originalImage = resizeToWidth(originalImage, 100);
333  
        
334  
        reproduceOpenEnd(originalImage, imageSurface);
335  
      }
336  
    }.start();
337  
  }
338  
  
339  
  static void reproduceOpenEnd(RGBImage original, ImageSurface imageSurface) {
340  
    Params best = null;
341  
    long lastPrint = 0;
342  
    for (int ntry = 1; ; ntry++) {
343  
      if (System.currentTimeMillis() >= lastPrint+1000) {
344  
        lastPrint = System.currentTimeMillis();
345  
        if (best == null)
346  
          System.out.println("Try " + ntry);
347  
        else {
348  
          System.out.println("Best: " + best);
349  
          System.out.println("Try " + ntry + ", score: " + formatDouble(best.getScore()*100, 2) + "%, structure size: " + structureSize(best, Params.class));
350  
        }
351  
      }
352  
      Params p = reproduce(original, ntry);
353  
      if (best == null || p != null && p.getScore() < best.getScore()) {
354  
        //System.out.println("New best! " + p.getScore());
355  
        best = p;
356  
        imageSurface.setImage(p.getImage());
357  
      }
358  
      
359  
      if (p != null && p.getScore() == 0.0)
360  
        break;
361  
    }
362  
  }
363  
  
364  
  static RGB probeRandomPixel(RGBImage image) {
365  
    int x = (int) (random()*(image.getWidth()-1));
366  
    int y = (int) (random()*(image.getHeight()-1));
367  
    return image.getPixel(x, y);
368  
  }
369  
  
370  
  static RGB randomColor() {
371  
    return new RGB(random(), random(), random());
372  
  }
373  
  
374  
  static RGBImage resizeToWidth(RGBImage image, int w) {
375  
    return resize(image, w, (int) ((image.getHeight()*(double) w)/image.getWidth()));
376  
  }
377  
  
378  
  public static RGBImage resize(RGBImage image, int w, int h) {
379  
    if (w == image.getWidth() && h == image.getHeight()) return image;
380  
381  
    int[] pixels = new int[w*h];
382  
    for (int y = 0; y < h; y++)
383  
      for (int x = 0; x < w; x++)
384  
        pixels[y*w+x] = image.getInt(x*image.getWidth()/w, y*image.getHeight()/h);
385  
    return new RGBImage(w, h, pixels);
386  
  }
387  
388  
  static boolean useImageCache = true;
389  
  static RGBImage loadImage(String snippetID) {
390  
   try {
391  
    File dir = new File(System.getProperty("user.home"), ".tinybrain/image-cache");
392  
    if (useImageCache) {
393  
      dir.mkdirs();
394  
      File file = new File(dir, snippetID + ".png");
395  
      if (file.exists() && file.length() != 0)
396  
        try {
397  
          return new RGBImage(ImageIO.read(file));
398  
        } catch (Throwable e) {
399  
          e.printStackTrace();
400  
          // fall back to loading from sourceforge
401  
        }
402  
    }
403  
404  
    String imageURL = getImageURL(parseSnippetID(snippetID));
405  
    System.err.println("Loading image: " + imageURL);
406  
    BufferedImage image = ImageIO.read(new URL(imageURL));
407  
408  
    if (useImageCache) {
409  
      File tempFile = new File(dir, snippetID + ".tmp." + System.currentTimeMillis());
410  
      ImageIO.write(image, "png", tempFile);
411  
      tempFile.renameTo(new File(dir, snippetID + ".png"));
412  
      //Log.info("Cached image.");
413  
    }
414  
415  
    //Log.info("Loaded image.");
416  
    return new RGBImage(image);
417  
   } catch (IOException e) {
418  
    throw new RuntimeException(e);
419  
   }
420  
  }
421  
422  
  static String getImageURL(long snippetID) throws IOException {
423  
    String url;
424  
    if (snippetID == 1000010 || snippetID == 1000012)
425  
      url = "http://tinybrain.de:8080/tb/show-blobimage.php?id=" + snippetID;
426  
    else
427  
      url = "http://eyeocr.sourceforge.net/filestore/filestore.php?cmd=serve&file=blob_" + snippetID
428  
        + "&contentType=image/png";
429  
    return url;
430  
  }
431  
432  
  public static long parseSnippetID(String snippetID) {
433  
    return Long.parseLong(shortenSnippetID(snippetID));
434  
  }
435  
436  
  private static String shortenSnippetID(String snippetID) {
437  
    if (snippetID.startsWith("#"))
438  
      snippetID = snippetID.substring(1);
439  
    String httpBlaBla = "http://tinybrain.de/";
440  
    if (snippetID.startsWith(httpBlaBla))
441  
      snippetID = snippetID.substring(httpBlaBla.length());
442  
    return snippetID;
443  
  }
444  
  
445  
  static Random _random = new Random();
446  
  static double random() {
447  
    return _random.nextInt(100001)/100000.0;
448  
  }
449  
  
450  
  static int random(int max) {
451  
    return _random.nextInt(max);
452  
  }
453  
  
454  
  static double random(double min, double max) {
455  
    return min+random()*(max-min);
456  
  }
457  
  
458  
  static void vsplit(RGBImage img, VSplit p) {
459  
    int w = img.getWidth(), h = img.getHeight();
460  
    for (int yy = 0; yy < h; yy++)
461  
      for (int xx = 0; xx < w; xx++) {
462  
        //double x = ((double) xx)/(w-1);
463  
        double y = ((double) yy)/(h-1);
464  
        RGB col = y <= p.splitPoint ? p.col1 : p.col2;
465  
        img.setPixel(xx, yy, col);
466  
      }
467  
  }
468  
  
469  
  public static double pixelDiff(RGB a, RGB b) {
470  
    return (Math.abs(a.r-b.r) + Math.abs(a.g-b.g) + Math.abs(a.b-b.b))/3;
471  
  }
472  
473  
  public static double diff(RGBImage image, RGBImage image2) {
474  
    int w = image.getWidth(), h = image.getHeight();
475  
    double sum = 0;
476  
    for (int y = 0; y < h; y++)
477  
      for (int x = 0; x < w; x++)
478  
        sum += pixelDiff(image.getRGB(x, y), image2.getRGB(x, y));
479  
    return sum/(w*h);
480  
  }
481  
  
482  
  public static void copy(RGBImage src, int srcX, int srcY, RGBImage dst, int dstX, int dstY, int w, int h) {
483  
    for (int y = 0; y < h; y++)
484  
      for (int x = 0; x < w; x++)
485  
        dst.setPixel(dstX+x, dstY+y, src.getPixel(srcX+x, srcY+y));
486  
  }
487  
  
488  
  public static int structureSize(Object o, Class baseClass) {
489  
    if (o == null) return 0;
490  
    int size = 1;
491  
    Class c = o.getClass();
492  
    if (c.isArray()) {
493  
      int n = Array.getLength(o);
494  
      for (int i = 0; i < n; i++)
495  
        size += structureSize(Array.get(o, i), baseClass);
496  
    } else
497  
      while (c != Object.class && c != baseClass) {
498  
        Field[] fields = c.getDeclaredFields();
499  
        for (Field field : fields) {
500  
          if ((field.getModifiers() & Modifier.STATIC) != 0)
501  
            continue;
502  
          if (field.getType().isPrimitive())
503  
            ++size;
504  
          else {
505  
            Object value = null;
506  
            try {
507  
              value = field.get(o);
508  
            } catch (IllegalAccessException e) {
509  
              throw new RuntimeException(e);
510  
            }
511  
            size += structureSize(value, baseClass);
512  
          }
513  
        }
514  
        c = c.getSuperclass();
515  
      }
516  
    return size;
517  
  }
518  
  
519  
  public static String formatDouble(double d, int digits) {
520  
    String format = "0.";
521  
    for (int i = 0; i < digits; i++) format += "#";
522  
    return new java.text.DecimalFormat(format, new java.text.DecimalFormatSymbols(Locale.ENGLISH)).format(d);
523  
  }
524  
525  
}

Author comment

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: 743 / 595
Referenced in: [show references]