f8g

ハーフトーニング(拡散誤差法)

パターンを用いたものではなく、空間フィルタリングのときのようなフィルタを掛けて2値化。

コード

これ使用

ImageProcessing.prototype.errorDiffuse = function(flt){
	var self = this;

	// init
	var w = this.canvas.width;
	var h = this.canvas.height;
	var sum = 0;                    // total of flt values
	var tmp = [];                   // temporary colors
	var fw  = flt[0].length;        // filter width
	var cur = parseInt(fw / 2, 10); // current pixel (X) of flt

	// init sum
	flt.forEach(function(_){
		_.forEach(function(n){
			sum += n;
		});
	});

	// init tmp
	for(var y = 0; y < h; y++){
		tmp[y] = [];
		for(var x = 0; x < w; x++){
			tmp[y][x] = 0;
		}
	}

	// filtering
	this.each(function(px, x, y){
		var e;
		var f = tmp[y][x] + px.average();

		if(f > 127){
			tmp[y][x] = 255;
			e = f - 255;
		}
		else{
			tmp[y][x] = 0;
			e = f;
		}

		flt.forEach(function(_, ny){
			var _y = y + ny;
			if(_y >= h) return;

			_.forEach(function(v, nx){
				var _x = x + nx - cur;

				if(0 > _x || _x >= w || !flt[ny][nx]) return;
				tmp[_y][_x] += e * v / sum;

			});
		});
	});

	tmp.forEach(function(_, y){
		_.forEach(function(v, x){
			self.setPixel(x, y, new ImageProcessing.Color(v, v, v));
		});
	});
}
  • フィルタ

フィルタは空間フィルタリングと似ているけど、下半分だけ定義する。

p-1.0 p0,0 p+1,0
p-1.+1 p0,+1 p+1,+1

(それぞれを値の合計で割る)

  • 参考(フィルタがいっぱい載ってる)

http://www.efg2.com/Lab/Library/ImageProcessing/DHALF.TXT

Floyd-Steinberg

var flt = [
	[0, 0, 7],
	[3, 5, 1]
];

http://media.tumblr.com/CAiSbEIuHcftfa81PCqqrMyi_500.png

Jarvis-Judice&Ninke

var flt = [
	[0, 0, 0, 7, 5],
	[3, 5, 7, 5, 3],
	[1, 3, 5, 3, 1]
];

http://media.tumblr.com/CAiSbEIuHcftfo9cbvhXRRar_500.png

その他

http://arikui.s101.xrea.com/test/canvas/cg/test/error_diffusion.html
今回はFirefoxでもできます。Operaよりは遅いです。

Firefox対応

http://github.com/arikui/image_processing.js/tree/master
opera-2dgameが使えない場合は、ImageDataを使ってgetPixel/setPixelをするようにした。単純に1ピクセルずつ黒く塗りつぶす処理で、ImageDataの方は2倍近く遅かった。ImageDataの方は指定した範囲のデータを一気に取得できるので、使いようでは速くなるのかもしれない。