Daily Creative Coding

元「30 min. Processing」。毎日、Creative Codingします。

パッチワークで画像を再構成する

f:id:aa_debdeb:20151029160438j:plain
/**
* Patchwork Image
*
* @author aa_debdeb
* @date 2015/10/30
*/


void setup(){
  size(512, 512);
  PImage image = loadImage("lena.jpg");
  image(image, 0, 0);
  
  loadPixels();
  color[][] colors = new color[width][height];
  for(int x = 0; x < width; x += 1){
    for(int y = 0; y < height; y += 1){
      colors[x][y] = pixels[y * width + x];
    }
  }
  updatePixels();
  
  ArrayList<Patch> patches = new ArrayList<Patch>();
  for(int i = 0; i < 100; i++){
    int x1 = int(random(width));
    int y1 = int(random(height));
    int patchWidth = int(random(40)) + 10;
    int x2 = x1 + patchWidth;
    int y2 = y1 + patchWidth;
    if(!(x2 > width - 1 || y2 > height - 1)){
      color[][] patch = new color[patchWidth][patchWidth];
      for(int x = 0; x < patchWidth; x++){
        for(int y = 0; y < patchWidth; y++){
          patch[x][y] = colors[x1 + x][y1 + y];
        }
      }
      patches.add(new Patch(patch));
    }
  }
  
  background(255);
  loadPixels();
  for(int i = 0; i < 10000; i++){
    int x = int(random(width));
    int y = int(random(height));
    color c = colors[x][y];
    Patch best = patches.get(0);
    for(Patch patch: patches){
      if(best.getDistance(c) > patch.getDistance(c)){
        best = patch;
      }
    }
    if(!(x + best.patch.length > width - 1 ||y + best.patch.length > height - 1)){ 
      for(int xx = 0; xx < best.patch.length; xx++){
        for(int yy = 0; yy < best.patch[0].length; yy++){
          pixels[(y + yy) * width + (x + xx)] = best.patch[xx][yy];
        }
      }
    }
  }
  updatePixels();
  
}

class Patch{
  
  color[][] patch;
  float r, g, b;
  
  Patch(color[][] patch){
    this.patch = patch;
    r = 0.0; g = 0.0; b = 0.0;
    for(int x = 0; x < patch.length; x++){
      for(int y = 0; y < patch[0].length; y++){
        r += red(patch[x][y]);
        g += green(patch[x][y]);
        b += blue(patch[x][y]);
      }
    }
    r /= patch.length * patch[0].length;
    g /= patch.length * patch[0].length;
    b /= patch.length * patch[0].length;
  }
  
  float getDistance(color c){
    return abs(r - red(c)) + abs(g - green(c)) + abs(b - blue(c));
  }
  
}