日常の進捗

主に自分のための,行為とその習慣化の記録

Mod: Coding Challenge #90: Floyd-Steinberg Dithering

f:id:takawo:20180118105335p:plain

チュートリアルではFloyd-Steinbergのディザを生成するアルゴリズムを使っているが,書き換えたプログラムでは便宜上16を4つのランダムな数字をつかって表すやり方でディザを作ってみている.

コード

import processing.pdf.*;
import java.util.Calendar;

PImage cat;
boolean savePDF;

void setup() {
  size(1024, 512);
}

void draw() {
  if (savePDF) {
    beginRecord(PDF, timestamp() + ".pdf");
  }
  cat = loadImage("cat.jpg");
  cat.filter(GRAY);
  background(255, 255, 255);

  image(cat, 0, 0);

  int n1 = max((int)random(8), 1);
  int n2 = max((int)random(16-n1), 1);
  int n3 = max((int)random(16-n1-n2), 1);
  int n4 = 16-n1-n2-n3;

  cat.loadPixels();
  for (int y = 0; y < cat.height-1; y++) {
    for (int x = 0; x < cat.width-1; x++) {
      color pix = cat.pixels[index(x, y)];
      float oldR = red(pix);
      float oldG = green(pix);
      float oldB = blue(pix);
      int factor = 1;
      int newR = round(factor * oldR / 255) * (255 / factor);
      int newG = round(factor * oldG / 255) * (255 / factor);
      int newB = round(factor * oldB / 255) * (255 / factor);
      cat.pixels[index(x, y)] = color(newR, newG, newB);

      float errR = oldR - newR;
      float errG = oldG - newG;
      float errB = oldB - newB;

      int index = index(x+1, y);
      color c = cat.pixels[index];
      float r = red(c);
      float g = green(c);
      float b = blue(c);
      r = r + errR * n1/16.0;
      g = g + errG * n1/16.0;
      b = b + errB * n1/16.0;
      cat.pixels[index] = color(r, g, b);

      index = index(x-1, y+1);
      c = cat.pixels[index];
      r = red(c);
      g = green(c);
      b = blue(c);
      r = r + errR * n2/16.0;
      g = g + errG * n2/16.0;
      b = b + errB * n2/16.0;
      cat.pixels[index] = color(r, g, b);

      index = index(x, y+1);
      c = cat.pixels[index];
      r = red(c);
      g = green(c);
      b = blue(c);
      r = r + errR * n3/16.0;
      g = g + errG * n3/16.0;
      b = b + errB * n3/16.0;
      cat.pixels[index] = color(r, g, b);


      index = index(x+1, y+1);
      c = cat.pixels[index];
      r = red(c);
      g = green(c);
      b = blue(c);
      r = r + errR * n4/16.0;
      g = g + errG * n4/16.0;
      b = b + errB * n4/16.0;
      cat.pixels[index] = color(r, g, b);
    }
  }

  cat.updatePixels();
  image(cat, 512, 0);
  noLoop();

  if (savePDF) {
    endRecord();
  }
}

void mousePressed() {
  redraw();
}

void keyPressed() {
  if (key == 's' || key == 'S') saveFrame(timestamp()+"_##.png");
  if (key == 'p' || key == 'P') savePDF = true;
}

String timestamp() {
  Calendar now = Calendar.getInstance();
  return String.format("%1$ty%1$tm%1$td_%1$tH%1$tM%1$tS", now);
}

int index(int x, int y) {
  return x + y * cat.width;
}

リファレンス

www.youtube.com