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

366
LINES

< > BotCompany Repo | #1000550 // Magnetize image (current)

JavaX source code [tags: use-pretranspiled] - run with: x30.jar

Libraryless. Click here for Pure Java version (1443L/10K/31K).

1  
!747
2  
3  
import java.awt.*;
4  
import java.awt.image.*;
5  
import javax.imageio.*;
6  
import static java.lang.Math.*;
7  
8  
!image classes
9  
!FrameWithImages
10  
11  
class P { double x, y; *(double *x, double *y) {} }
12  
13  
interface Reproducer {
14  
  public main.Params reproduce(RGBImage original);
15  
}
16  
  
17  
interface ReproducerMaker {
18  
  public Reproducer make();
19  
}
20  
21  
main {
22  
  static Object androidContext;
23  
  static int imageWidth = 200;
24  
  
25  
  !include #1000522 // helper functions for image reproduction
26  
  !include #1000898 // exitOnFrameClose
27  
  
28  
  static double pi = PI;
29  
  
30  
  static double rotate_x(P p, double angle) {
31  
    angle = angle*pi/180;
32  
    return p.x*cos(angle)-p.y*sin(angle);
33  
  }
34  
  
35  
  static double sideshiftlimit = sqrt(2)/2;
36  
    
37  
  static class Magnet extends Params {
38  
    double angle, sideshift;
39  
    RGB col1 = new RGB(Color.black), col2 = new RGB(Color.white);
40  
    
41  
    RGB def(double x, double y) {
42  
      P p = new P(x-0.5, y-0.5);
43  
      x = rotate_x(p, -angle);
44  
      return x < sideshift ? col1 : col2;
45  
    }
46  
    
47  
    Magnet copy() {
48  
      new Magnet p;
49  
      baseClone(p);
50  
      p.sideshift = sideshift;
51  
      p.angle = angle;
52  
      p.col1 = col1;
53  
      p.col2 = col2;
54  
      return p;
55  
    }
56  
    
57  
    public String toString() {
58  
      return "M " + formatDouble(sideshift, 2) + " " + (int) angle + " " + col1 + " " + col2;
59  
    }
60  
61  
    RGBImage render() {
62  
      int w = originalImage.getWidth(), h = originalImage.getHeight();
63  
      RGBImage image = new RGBImage(w, h, Color.white);
64  
      paint(image, this);
65  
      return image;
66  
    }
67  
  }
68  
69  
  static abstract class Params {
70  
    RGBImage originalImage;
71  
    abstract RGBImage render();
72  
    abstract Params copy();
73  
    
74  
    void baseClone(Params p) {
75  
      p.originalImage = originalImage;
76  
    }
77  
    
78  
    RGBImage rendered;
79  
    RGBImage getImage() {
80  
      if (rendered == null)
81  
        rendered = render();
82  
      return rendered;
83  
    }
84  
    
85  
    double score = 2.0;
86  
    double getScore() {
87  
      if (score == 2.0)
88  
        score = calcScore();
89  
      return score;
90  
    }
91  
    
92  
    double calcScore() {
93  
      return diff(originalImage, getImage());
94  
    }
95  
    
96  
    boolean isBetterThan(Params p) {
97  
      return getScore() < p.getScore();
98  
    }
99  
  }
100  
  
101  
  static class RandomMagnet implements Reproducer {
102  
    int n = -1;
103  
    public Params reproduce(RGBImage original) {
104  
      ++n;
105  
      new Magnet p;
106  
      p.originalImage = original;
107  
      p.sideshift = random(-sideshiftlimit, sideshiftlimit);
108  
      p.angle = random()*360;
109  
      if (n % 2 == 0) {
110  
        p.col1 = randomColor();
111  
        p.col2 = randomColor();
112  
      } else {
113  
        p.col1 = probeRandomPixel(original);
114  
        p.col2 = probeRandomPixel(original);
115  
      }
116  
      return p;
117  
    }
118  
  }
119  
  
120  
  static class VaryBest implements Reproducer {
121  
    Reproducer base;
122  
    Params best;
123  
    
124  
    VaryBest(Reproducer base) {
125  
      this.base = base;
126  
    }
127  
    
128  
    public Params reproduce(RGBImage original) {
129  
      Params p = base.reproduce(original);
130  
      if (best == null || p.isBetterThan(best))
131  
        best = p;
132  
      Params variation = vary(best);
133  
      //System.out.println("Best: " + best.getScore() + ", variation: " + variation.getScore());
134  
      if (variation.isBetterThan(best)) {
135  
        //System.out.println("Using variation, diff=" + (best.getScore()-variation.getScore()));
136  
        best = variation;
137  
      }
138  
      return best;
139  
    }
140  
    
141  
    Params vary(Params p) {
142  
      if (p instanceof Magnet) {
143  
        Magnet n = ((Magnet) p).copy();
144  
        int s = random(3);
145  
        if (s == 0) {
146  
          s = random(2);
147  
          if (s == 0)
148  
            n.sideshift = varySideshift(n.sideshift);
149  
          else {
150  
            //double old = n.angle;
151  
            n.angle = (n.angle+360+random(-5, 5)) % 360;
152  
            //System.out.println("angle: " + formatDouble(old, 1) + " -> " + formatDouble(n.angle, 1));
153  
          }
154  
        } else if (s == 1)
155  
          n.col1 = varyColor(n.col1);
156  
        else
157  
          n.col2 = varyColor(n.col2);
158  
        return n;
159  
      }
160  
      
161  
      return null;
162  
    }
163  
    
164  
    double varySideshift(double sideshift) {
165  
      return max(-sideshiftlimit, min(sideshiftlimit, sideshift+random(-0.1, 0.1)));
166  
    }
167  
    
168  
    double varyN(double x) {
169  
      return Math.max(0, Math.min(1, x+random(-0.1, 0.1)));
170  
    }
171  
    
172  
    float varyChannel(float x) {
173  
      return Math.max(0f, Math.min(1f, (float) (x+random(-0.1, 0.1))));
174  
    }
175  
    
176  
    RGB varyColor(RGB rgb) {
177  
      int s = random(3);
178  
      if (s == 0)
179  
        return new RGB(varyChannel(rgb.r), rgb.g, rgb.b);
180  
      else if (s == 1)
181  
        return new RGB(rgb.r, varyChannel(rgb.g), rgb.b);
182  
      else
183  
        return new RGB(rgb.r, rgb.g, varyChannel(rgb.b));
184  
    }
185  
  }
186  
187  
  static class Gridded extends Params {
188  
    int w, h;
189  
    Params[] array;
190  
    
191  
    Gridded(int w, int h) {
192  
      this.w = w;
193  
      this.h = h;
194  
      array = new Params[w*h];
195  
    }
196  
    
197  
    Gridded copy() {
198  
      Gridded p = new Gridded(w, h);
199  
      baseClone(p);
200  
      for (int i = 0; i < w*h; i++)
201  
        p.array[i] = array[i].copy();
202  
      return p;
203  
    }
204  
    
205  
    public String toString() {
206  
      StringBuilder buf = new StringBuilder("grid{");
207  
      for (int i = 0; i < w*h; i++) {
208  
        if (i != 0)
209  
          buf.append(", ");
210  
        buf.append(array[i]);
211  
      }
212  
      return buf + "}";
213  
    }
214  
    
215  
    public RGBImage render() {
216  
      int ow = originalImage.getWidth(), oh = originalImage.getHeight();
217  
      RGBImage img = new RGBImage(ow, oh, Color.white);
218  
      for (int y = 0; y < h; y++)
219  
        for (int x = 0; x < w; x++) {
220  
          int x1 = x*ow/w, y1 = y*oh/h;
221  
          int x2 = (x+1)*ow/w, y2 = (y+1)*oh/h;
222  
          RGBImage part = array[y*w+x].render();
223  
          main.copy(part, 0, 0, img, x1, y1, part.getWidth(), part.getHeight());
224  
        }
225  
      return img;
226  
    }
227  
  }
228  
  
229  
  static class Grid implements Reproducer {
230  
    int w, h;
231  
    Reproducer[] bases;
232  
    
233  
    Grid(ReproducerMaker maker, int w, int h) {
234  
      this.w = w;
235  
      this.h = h;
236  
      bases = new Reproducer[w*h];
237  
      for (int i = 0; i < w*h; i++)
238  
        bases[i] = maker.make();
239  
    }
240  
    
241  
    RGBImage getGridElement(RGBImage originalImage, int i) {
242  
      int ow = originalImage.getWidth(), oh = originalImage.getHeight();
243  
      int y = i / w;
244  
      int x = i % w;
245  
      int x1 = x*ow/w, y1 = y*oh/h;
246  
      int x2 = (x+1)*ow/w, y2 = (y+1)*oh/h;
247  
      return originalImage.clip(x1, y1, x2-x1, y2-y1);
248  
    }
249  
      
250  
    public Params reproduce(RGBImage original) {
251  
      Gridded gridded = new Gridded(w, h);
252  
      gridded.originalImage = original;
253  
      for (int i = 0; i < w*h; i++) {
254  
        RGBImage img = getGridElement(original, i);
255  
        Params p = bases[i].reproduce(img);
256  
        if (p == null)
257  
          return null;
258  
        gridded.array[i] = p;
259  
      }
260  
      return gridded;
261  
    }
262  
  }
263  
  
264  
  static ReproducerMaker baseMaker = new ReproducerMaker() {
265  
    public Reproducer make() {
266  
      return new VaryBest(new RandomMagnet());
267  
    }
268  
  };
269  
    
270  
  // main reproduce function
271  
  static Reproducer reproducer;
272  
273  
  static String imageID = "#1000326"; // Bryan Cranston!
274  
  static RGBImage originalImage;
275  
  static FrameWithImages fwi;
276  
  static double zoom = 1;
277  
    
278  
  psvm {
279  
    for (int i = 0; i < args.length; i++) {
280  
      String arg = args[i];
281  
      if (isSnippetID(arg))
282  
        imageID = arg;
283  
      else if (arg.equals("zoom"))
284  
        zoom = Double.parseDouble(args[++i]);
285  
      else if (arg.equals("w") || arg.equals("width")) {
286  
        String w = args[++i];
287  
        imageWidth = w.equals("original") ? -1 : Integer.parseInt(w);
288  
      } else
289  
        System.out.println("Unknown argument: " + arg);
290  
    }
291  
292  
    fwi = new FrameWithImages(1);
293  
    fwi.hop();
294  
    
295  
    thread {
296  
      originalImage = loadImage(imageID);
297  
      if (imageWidth < 0)
298  
        imageWidth = originalImage.getWidth();
299  
      else
300  
        originalImage = resizeToWidth(originalImage, imageWidth);
301  
      fwi.setZoom(zoom);
302  
      fwi.setInnerSize(originalImage);
303  
      
304  
      int gx = originalImage.getWidth()/8, gy = originalImage.getHeight()/8;
305  
      reproducer = new Grid(baseMaker, gx, gy);
306  
      
307  
      reproduceOpenEnd(originalImage);
308  
    }
309  
    
310  
    /*
311  
    new Magnet m;
312  
    m.sideshift = -0.2;
313  
    m.angle = 30;
314  
    
315  
    while (true) {
316  
      m.angle = (m.angle+1) % 360;
317  
      //System.out.println("Angle: " + m.angle);
318  
      RGBImage img = new RGBImage(100, 100, Color.gray);
319  
      paint(img, m);
320  
      fwi.setImage(0, img);
321  
    }
322  
    */
323  
  }
324  
  
325  
  
326  
  static void reproduceOpenEnd(RGBImage original) {
327  
    Params best = null;
328  
    long lastPrint = 0, lastN = 0;
329  
    for (long ntry = 1; ; ntry++) {
330  
      long now = System.currentTimeMillis();
331  
      if (now >= lastPrint+1000) {
332  
        long tps = (ntry-lastN)*1000/(now-lastPrint);
333  
        lastPrint = now;
334  
        lastN = ntry;
335  
        String s = "Try " + ntry + "(" + tps + "/s)";
336  
        if (best == null)
337  
          System.out.println(s);
338  
        else {
339  
          //System.out.println("Best: " + best);
340  
          System.out.println(s + ", score: " + formatDouble(best.getScore()*100, 3) + "%");
341  
          //, structure size: " + structureSize(best, Params.class));
342  
        }
343  
      }
344  
      Params p = reproducer.reproduce(original);
345  
      if (best == null || p != null && p.getScore() < best.getScore()) {
346  
        //System.out.println("New best! " + p.getScore());
347  
        best = p;
348  
        fwi.setImage(0, p.getImage());
349  
      }
350  
      
351  
      if (p != null && p.getScore() == 0.0)
352  
        break;
353  
    }
354  
  }
355  
  
356  
  static void paint(RGBImage img, Magnet m) {
357  
    int w = img.getWidth(), h = img.getHeight();
358  
    for (int y = 0; y < h; y++)
359  
      for (int x = 0; x < w; x++) {
360  
        double nx = x/(double)(w-1);
361  
        double ny = y/(double)(h-1);
362  
        img.setPixel(x, y, m.def(nx, ny));
363  
      }
364  
  }
365  
  
366  
}

Author comment

Began life as a copy of #1000541

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: #1000550
Snippet name: Magnetize image (current)
Eternal ID of this version: #1000550/1
Text MD5: b547d264a0550449b25f102aaac558ae
Transpilation MD5: 29ca80eb49bc360e234d561d4182b960
Author: stefan
Category:
Type: JavaX source code
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2015-09-13 15:10:58
Source code size: 10027 bytes / 366 lines
Pitched / IR pitched: No / Yes
Views / Downloads: 566 / 544
Referenced in: [show references]