誤差拡散
Libcaca study - 3. Error diffusion
こちらを参考にして試してみた
左から
FloydSteinberg
JaJuNi(Jarvis, Judice, and Ninke)
FloydSteinbergDervatives
ShiauFan
ShiauFan2
Stucki
Burkes
Sierra
SierraTwoRow
SierraLite
Atkinson
?
PixelFormats.BlackWhite
一覧画像
こっちのほうが見やすいかな
使ったアプリ
表示できるのはアプリに埋め込んだ画像のこれだけ
一番上のCopyボタンは2値化画像をクリップボードへコピーする
その下のPixelFormatsBlackWhiteはFormatConvertedBitmapクラスを使ってピクセルフォーマットをBlackWhiteに変換する
それ以下のボタンはそれぞれの方法で誤差拡散
2値画像を左クリック中は元のグレースケール画像を表示する
ファイル名:20200402_誤差拡散2値.zip
普通の画像で
画像サイズが大きすぎてはてなブログだと縮小表示になるから、右クリックメニューから別のタブで開かないと正しく表示されないねえ
これは正しく等倍表示されている
輝度250のグレースケール画像
輝度128のグレースケール画像
拡散範囲が広いものほどゴワゴワする感じ、AtkinsonとPixelFormatsBlackWhiteは均一になった
/// <summary> /// 誤差拡散、FloydSteinberg、PixelFormat.Gray8グレースケール画像専用 /// </summary> /// <param name="source">元画像のピクセルの輝度値</param> /// <param name="width"></param> /// <param name="height"></param> /// <param name="stride">横1行分のbyte数</param> /// <returns></returns> private BitmapSource D1_FloydSteinberg(byte[] source, int width, int height, int stride) { int count = source.Length; byte[] pixels = new byte[count];//変換先画像用 double[] gosaPixels = new double[count];//誤差計算用 Array.Copy(source, gosaPixels, count); int p, yp;//座標 double gosa;//誤差(変換前 - 変換後) // * 7 //3 5 1 // ̄16 ̄ for (int y = 0; y < height; y++) { yp = y * stride; for (int x = 0; x < width; x++) { //注目ピクセルのインデックス p = yp + x; //しきい値127.5未満なら0にする、それ以外は255にする SetBlackOrWhite(gosaPixels[p], pixels, p); //誤差拡散 gosa = (gosaPixels[p] - pixels[p]) / 16.0; if (x != width - 1) //右 gosaPixels[p + 1] += gosa * 7; if (y < height - 1) { p += stride; //下 gosaPixels[p] += gosa * 5; if (x != 0) //左下 gosaPixels[p - 1] += gosa * 3; if (x != width - 1) //右下 gosaPixels[p + 1] += gosa * 1; } } } return BitmapSource.Create(width, height, 96, 96, PixelFormats.Gray8, null, pixels, stride); } /// <summary> /// しきい値127.5で 0 or 255、127.5未満は0、127.5以上は255に置き換える /// 127.49999999999999999...は0、127.5以上は255だから、整数の場合は127.5を四捨五入した128未満が0、それ以外は255にすればいい? /// </summary> /// <param name="value">対象の値</param> /// <param name="pixels">0 or 255を入れる配列</param> /// <param name="p">配列のIndex</param> private void SetBlackOrWhite(double value, byte[] pixels, int p) { if (127.5 > value) pixels[p] = 0; else pixels[p] = 255; }
関連記事
次回のWPF記事は翌日
前回のWPF記事は昨日
1ヶ月後
gogowaten.hatenablog.com
ガンマ補正したほうが元の画像に近くなる
前回の誤差拡散は2年前