Processingで写真や画像をドット絵に変換するソフトを作ってみました

ドット絵とか、いいよな

 ふと「ドット絵とか、いいよな」という思いに取り憑かれ、写真をドット絵に変換するソフトを作ってみました。
 フリーソフトでいいやつないかなと思って探してたのですが、意外にしっくりくるものがないので、仕方なく自分でつくりました。1時間考えながら散歩してたら、なんとなくアルゴリズムが出来上がったので30分くらいで書き上げました。特に苦労したところや工夫したところはないです。

120918_Factory01
 これが元絵

四日市工場夜景 自作ソフトでドット絵加工
 これがドット絵加工した絵

 これをInstagramにアップしたら@monestarさんから以下のようなコメント

 早速やってみました。

四日市工場夜景 自作ソフトでドット絵加工 元絵と多重露光処理
 元絵とドット絵を合成

 か、かっこいい!さすが変デジ研究所所長。的確なアドバイスでした。

 ソースコード、大したもんじゃないので惜しげ無く公開します。Processingさえダウンロードしてコピペして実行すればすぐできるので。デフォルトのサイズはInstagramに最適化(612×612)されています。
 動画にも対応したので、そちらは気が向いたら適当に公開します。

とびだせどうぶつの森のマイデザイン補助ツールに応用

 なんとこのプログラムが「どうぶつの森」のマイデザイン補助ツールとして使えると言うことで急遽専用のツールを作成いたしました。以下参照下さい。

ドット絵にするプログラム

 実行したら、画像を選ぶだけでドット絵が生成されます。画像保存したいときは「p」ボタン。「d」ボタン押すと元絵との多重露光します。もう一回「d」押すと元に戻ります。ドットを増やしたいときはsize_x, size_y、ドットの枠野太さをかえたいときはdotframe, ドットの大きさを変えたいときはscaleの数字を変えてね。size_x, size_yの比率は選択する画像の比率に合わせるとよいです。

PImage img0;
PImage writeImg;

//dot parameters
int size_x = 51;
int size_y = 51;
int dotframe = 1;
int scale = 12;

boolean dxp = false;

void setup() {
  size(size_x*scale, size_y*scale);
  println("select under exposed photo.");
  String imgPath = selectInput();
  img0 = loadImage(imgPath);
  writeImg = createGraphics(size_x*scale, size_y*scale, P2D);
}

void draw(){
  img0.loadPixels();

  // making image-----
  float[] img_r = new float[img0.width*img0.height];
  float[] img_g = new float[img0.width*img0.height];
  float[] img_b = new float[img0.width*img0.height];

  float[] img16_r = new float[size_x*size_y];
  float[] img16_g = new float[size_x*size_y];
  float[] img16_b = new float[size_x*size_y];

  for(int i = 0; i < img0.width*img0.height; i++){
    color tmp_color = img0.pixels[i];
    img_r[i] = red(tmp_color);
    img_g[i] = green(tmp_color);
    img_b[i] = blue(tmp_color);
  }

  int div_x = int(img0.width / size_x);
  int div_y = int(img0.height / size_y);

  float tmp_r;
  float tmp_g;
  float tmp_b;

  // makeing dot image
  for(int i = 0; i < size_x*size_y; i++){
    tmp_r = 0;
    tmp_g = 0;
    tmp_b = 0;
    int tmp_y = int(i / size_x);
    int tmp_x = i - size_x*tmp_y;

    for(int j = 0; j < div_x; j++){
       for(int k = 0; k < div_y; k++){
         tmp_r += img_r[tmp_x*div_x + tmp_y*img0.width*div_y+ j + k*img0.width];
         tmp_g += img_g[tmp_x*div_x + tmp_y*img0.width*div_y+ j + k*img0.width];
         tmp_b += img_b[tmp_x*div_x + tmp_y*img0.width*div_y+ j + k*img0.width];
       }
    }

    tmp_r = tmp_r/(div_x*div_y);
    tmp_g = tmp_g/(div_x*div_y);
    tmp_b = tmp_b/(div_x*div_y);
    
    img16_r[i] = tmp_r;
    img16_g[i] = tmp_g;
    img16_b[i] = tmp_b;
  }

  // scaling dot image
  writeImg.loadPixels();
  for(int i = 0; i < size_x*size_y; i++){
    int tmp_y = int(i / size_x);
    int tmp_x = i - size_x*tmp_y;

    for(int j = 0; j < scale; j++){
      for(int k = 0; k < scale; k++){
        writeImg.pixels[tmp_y*size_x*scale*scale+tmp_x*scale+j*size_x*scale+k] = color(img16_r[i], img16_g[i], img16_b[i]);
      }
    }
  }

  // draw frame
  for(int i = 0; i < size_x*size_y; i++){
    int tmp_y = int(i / size_x);
    int tmp_x = i - size_x*tmp_y;

    for(int j = scale-dotframe; j < scale; j++){
      for(int k = 0; k < scale; k++){
        writeImg.pixels[tmp_y*size_x*scale*scale+tmp_x*scale+j*size_x*scale+k] = color(255, 255, 255);
      }
    }
  }

  for(int i = 0; i < size_x*size_y; i++){
    int tmp_y = int(i / size_x);
    int tmp_x = i - size_x*tmp_y;

    for(int j = 0; j < scale; j++){
      for(int k = scale-dotframe; k < scale; k++){
        writeImg.pixels[tmp_y*size_x*scale*scale+tmp_x*scale+j*size_x*scale+k] = color(255, 255, 255);
      }
    }
  }
  writeImg.updatePixels();
  
  //dxp
  if(dxp == true){
    background(writeImg);
    image(img0, 0, 0, width, height);
    blend(writeImg, 0, 0, width, height, 0 ,0, width, height, SCREEN);
  }else{
    image(writeImg, 0, 0, width, height);    
  }
}


void keyPressed() {
  // save image
  if(key == 'p' || key == 'P') {
    save("screenshot.jpg"); 
    println("screen saved."); 
  }

  if(key == 'd' || key == 'D'){
    if(dxp == true){
      dxp = false;
    }else{
      dxp = true;
    }
  }

  // exit
  if(key == ' ') {
    exit();
  }
}