みさご解体新書

ランダムディザリング

実行例

ソースコード

TypeScript

0.jpg / app.ts

解説/アルゴリズム

  1. ピクセルから色を取り出し、明るさを計算する。
  2. 明るさ / 明るさの最大値の確率で白、そうでなければ黒の色で対象のピクセルを塗りつぶす。

例えば明るさが 10 で、明るさの最大値が 255 の場合、10/255 で約 4% の確率で白、約 96% の確率で黒に変換する。

つまり、対象ピクセルの明るさが低ければ黒になる確率が高くなり、逆に明るさが高ければ白になる確率が高くなる。

コード例

import * as p5 from "p5";

new p5((p: p5) => {
  let image: p5.Image;

  p.preload = () => {
    image = p.loadImage("./0.jpg");
  };

  p.setup = () => {
    p.createCanvas(p.windowWidth, p.windowHeight);
    image.loadPixels();

    // 画像の全ピクセルを走査
    for (let y = 0; y < image.height; y++) {
      for (let x = 0; x < image.width; x++) {
        // 対象のピクセルを取り出す
        const color = getPixel(x, y);

        // 取り出したピクセルからRGBを抽出
        const r = p.red(color);
        const g = p.green(color);
        const b = p.blue(color);

        // グレースケール値(明るさ)を計算
        const gray = 0.299 * r + 0.587 * g + 0.114 * b;

        // 明るさ / 明るさの最大値の確率で白、そうでなければ黒の色にする
        let d = 255;
        if (gray <= p.random(0, 255)) {
          d = 0;
        }

        // 白か黒をピクセルにセットし直す
        setPixel(x, y, [d, d, d]);
      }
    }

    image.updatePixels();
    p.image(image, 0, 0);
  };

  function getPixel(x: number, y: number): number[] {
    const i = (y * image.width + x) * 4;
    return [
      image.pixels[i],
      image.pixels[i + 1],
      image.pixels[i + 2],
      image.pixels[i + 3],
    ];
  }

  function setPixel(x: number, y: number, color: number[]): void {
    const i = (y * image.width + x) * 4;
    image.pixels[i + 0] = color[0];
    image.pixels[i + 1] = color[1];
    image.pixels[i + 2] = color[2];
  }
});

内部で利用しているアルゴリズム

グレースケール, 二値化