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

447
LINES

< > BotCompany Repo | #1000541 // Magnets

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

Libraryless. Click here for Pure Java version (1693L/12K/37K).

!636

import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;
import static java.lang.Math.*;

!standard functions
!image classes
!FrameWithImages
!quicknew
!* ctr
!721 // thread {

class P { double x, y; *(double *x, double *y) {} }

interface Reproducer {
  public main.Params reproduce(RGBImage original);
}
  
interface ReproducerMaker {
  public Reproducer make();
}

main {
  static int imageWidth = 200;
  
  !include #1000522 // helper functions for image reproduction
  
  static double pi = PI;
  
  static double rotate_x(P p, double angle) {
    angle = angle*pi/180;
    return p.x*cos(angle)-p.y*sin(angle);
  }
  
  static class Magnet extends Params {
    double cx, cy, angle;
    RGB col1 = new RGB(Color.black), col2 = new RGB(Color.white);
    
    RGB def(double x, double y) {
      P p = new P(x-cx, y-cy);
      x = rotate_x(p, -angle);
      return x < 0 ? col1 : col2;
    }
    
    Magnet copy() {
      new Magnet p;
      baseClone(p);
      p.cx = cx;
      p.cy = cy;
      p.angle = angle;
      p.col1 = col1;
      p.col2 = col2;
      return p;
    }
    
    public String toString() {
      return "M " + formatDouble(cx, 2) + " " + formatDouble(cy, 2) + " " + (int) angle + " " + col1 + " " + col2;
    }

    RGBImage render() {
      int w = originalImage.getWidth(), h = originalImage.getHeight();
      RGBImage image = new RGBImage(w, h, Color.white);
      paint(image, this);
      return image;
    }
  }

  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() {
      return diff(originalImage, getImage());
    }
    
    boolean isBetterThan(Params p) {
      return getScore() < p.getScore();
    }
  }
  
  static class SlantedSplit extends Params {
    double splitPointL, splitPointR;
    RGB col1, col2;
    boolean swap;
    
    SlantedSplit copy() {
      SlantedSplit p = new SlantedSplit();
      baseClone(p);
      p.splitPointL = splitPointL;
      p.splitPointR = splitPointR;
      p.col1 = col1;
      p.col2 = col2;
      p.swap = swap;
      return p;
    }
    
    public String toString() {
      return (swap ? "SlantedHSplit " : "SlantedVSplit ") + splitPointL + " " + splitPointR + " " + col1 + " " + col2;
    }

    RGBImage render() {
      int w = originalImage.getWidth(), h = originalImage.getHeight();
      RGBImage image = new RGBImage(w, h, Color.white);
      slantedSplit(image, this);
      return image;
    }
  }
  
  static class RandomMagnet implements Reproducer {
    int n = -1;
    public Params reproduce(RGBImage original) {
      ++n;
      new Magnet p;
      p.originalImage = original;
      p.cx = random();
      p.cy = random();
      p.angle = random()*360;
      if (n % 2 == 0) {
        p.col1 = randomColor();
        p.col2 = randomColor();
      } else {
        p.col1 = probeRandomPixel(original);
        p.col2 = probeRandomPixel(original);
      }
      return p;
    }
  }
  
  static class RandomSlantedSplit implements Reproducer {
    int n = -1;
    public Params reproduce(RGBImage original) {
      ++n;
      SlantedSplit p = new SlantedSplit();
      p.swap = random(2) == 0;
      p.originalImage = original;
      p.splitPointL = random();
      p.splitPointR = random();
      if (n % 2 == 0) {
        p.col1 = randomColor();
        p.col2 = randomColor();
      } else {
        p.col1 = probeRandomPixel(original);
        p.col2 = 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 SlantedSplit) {
        SlantedSplit n = ((SlantedSplit) 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;
      }
      
      if (p instanceof Magnet) {
        Magnet n = ((Magnet) p).copy();
        int s = random(3);
        if (s == 0) {
          s = random(3);
          if (s == 0)
            n.cx = varyN(n.cx);
          else if (s == 1)
            n.cy = varyN(n.cy);
          else {
            //double old = n.angle;
            n.angle = (n.angle+360+random(-5, 5)) % 360;
            //System.out.println("angle: " + formatDouble(old, 1) + " -> " + formatDouble(n.angle, 1));
          }
        } else if (s == 1)
          n.col1 = varyColor(n.col1);
        else
          n.col2 = varyColor(n.col2);
        return n;
      }
      
      return null;
    }
    
    void varySplitPoint(SlantedSplit p) {
      if (random(2) == 0)
        p.splitPointL = Math.max(0, Math.min(1, p.splitPointL+random(-0.1, 0.1)));
      else
        p.splitPointR = Math.max(0, Math.min(1, p.splitPointR+random(-0.1, 0.1)));
    }
    
    double varyN(double x) {
      return Math.max(0, Math.min(1, x+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 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 RandomSlantedSplit());
      return new VaryBest(new RandomMagnet());
    }
  };
    
  // main reproduce function
  static Reproducer reproducer;

  static String imageID = "#1000326"; // Bryan Cranston!
  static RGBImage originalImage;
  static FrameWithImages fwi;
  static double zoom = 1;
    
  psvm {
    for (int i = 0; i < args.length; i++) {
      String arg = args[i];
      if (isSnippetID(arg))
        imageID = arg;
      else if (arg.equals("zoom"))
        zoom = Double.parseDouble(args[++i]);
      else if (arg.equals("w") || arg.equals("width")) {
        String w = args[++i];
        imageWidth = w.equals("original") ? -1 : Integer.parseInt(w);
      } else
        System.out.println("Unknown argument: " + arg);
    }

    fwi = new FrameWithImages(1);
    fwi.hop();
    
    thread {
      originalImage = loadImage(imageID);
      if (imageWidth < 0)
        imageWidth = originalImage.getWidth();
      else
        originalImage = resizeToWidth(originalImage, imageWidth);
      fwi.setZoom(zoom);
      fwi.setInnerSize(originalImage);
      
      int gx = originalImage.getWidth()/8, gy = originalImage.getHeight()/8;
      reproducer = new Grid(baseMaker, gx, gy);
      
      reproduceOpenEnd(originalImage);
    }
    
    /*
    new Magnet m;
    m.cx = m.cy = 0.5;
    m.angle = 30;
    
    while (true) {
      m.angle = (m.angle+1) % 360;
      //System.out.println("Angle: " + m.angle);
      RGBImage img = new RGBImage(100, 100, Color.gray);
      paint(img, m);
      fwi.setImage(0, img);
    }
    */
  }
  
  
  static void reproduceOpenEnd(RGBImage original) {
    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, 3) + "%, structure size: " + structureSize(best, Params.class));
        }
      }
      Params p = reproducer.reproduce(original);
      if (best == null || p != null && p.getScore() < best.getScore()) {
        //System.out.println("New best! " + p.getScore());
        best = p;
        fwi.setImage(0, p.getImage());
      }
      
      if (p != null && p.getScore() == 0.0)
        break;
    }
  }
  
  static void paint(RGBImage img, Magnet m) {
    int w = img.getWidth(), h = img.getHeight();
    for (int y = 0; y < h; y++)
      for (int x = 0; x < w; x++) {
        double nx = x/(double)(w-1);
        double ny = y/(double)(h-1);
        img.setPixel(x, y, m.def(nx, ny));
      }
  }
  
  static void slantedSplit(RGBImage img, SlantedSplit 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);
        if (p.swap) {
          double temp = x; x = y; y = x;
        }
        double splitPoint = mix(p.splitPointL, p.splitPointR, x);
        RGB col = y <= splitPoint ? p.col1 : p.col2;
        img.setPixel(xx, yy, col);
      }
  }
}

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: #1000541
Snippet name: Magnets
Eternal ID of this version: #1000541/1
Text MD5: 66d2c6768f5aa7ea4551cfc04b36a020
Transpilation MD5: b4efe870ebabf77f0d2a98e80e12e58f
Author: stefan
Category:
Type: JavaX source code
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2015-08-14 13:56:21
Source code size: 12324 bytes / 447 lines
Pitched / IR pitched: No / Yes
Views / Downloads: 780 / 885
Referenced in: #1000550 - Magnetize image (current)
#3000189 - Answer for stefanreich(>> t bla)
#3000190 - Answer for stefanreich(>> t 20 questions)
#3000382 - Answer for ferdie (>> t = 1, f = 0)
#3000383 - Answer for funkoverflow (>> t=1, f=0 okay)