4

数か月前に作成した Paint.net のプラグインを更新しています。これは Simulate Color Depth と呼ばれ、画像の色数を選択した BPP に減らします。長い間ディザリングが含まれていましたが、ディザリングを注文したことはありません。それがあればいいと思ったので、何か役に立つものをインターネットで検索し始めました疑似コードに書かれている通りにする

for (int y = 0; x < image.Height; y++)
{  
    for (int x = 0; x < image.Width; x++)
    {
        Color color = image.GetPixel(x, y);  
        color.R = color.R + bayer8x8[x % 8, y % 8];  
        color.G = color.G + bayer8x8[x % 8, y % 8];  
        color.B = color.B + bayer8x8[x % 8, y % 8];  
        image.SetPixel(x, y, GetClosestColor(color, bitdepth);  
    }  
}

しかし、結果が明るすぎるので、wikiページをもう一度チェックすることにしました。すると、しきい値マップの右側に「1/65」があり、両方のエラー拡散を考えさせられました(はい、知っています、変ですね?) 取得した値bayer8x8[x % 8, y % 8]を 65 で割り、その値をカラー チャネルで乗算しますが、結果が乱雑であるか、またはまだ明るすぎます (覚えているように) が、結果は他の場所で見たようなものではありませんでした。明るすぎる、コントラストが高すぎる、または乱雑で、インターネットを検索しても本当に役立つものは見つかりませんでした。このベイヤーディザリングを正しく機能させる方法を知っている人はいますか?

前もってありがとう、クッキー

4

3 に答える 3

5

元のアルゴリズム (ウィキペディアから) に問題はないと思います。明るさの不均衡は、おそらくモニター ガンマのアーティファクトです。Joel Yliluoma 's Positional Dithering Algorithm、Joel Yliluoma によって発明されたディザリング アルゴリズムに関するこの記事のガンマ補正に関する付録 ( http://bisqwit.iki.fi/story/howto/dither/jy/#Appendix%201GammaCorrection ) を確認して、効果の説明 (注意: ページはグラフィックがかなり多い)。

ちなみに、おそらくその記事で詳述されている(明らかにパブリックドメインの)アルゴリズムが問題の解決策になる可能性があります...

于 2012-01-22T08:05:57.317 に答える
2

これを試して:

color.R = color.R + bayer8x8[x % 8, y % 8] * GAP / 65;

ここで GAP は、2 つの最も近い色のしきい値の間の距離である必要があります。これは、ピクセルあたりのビット数に依存します。

たとえば、各ピクセルの赤成分に 4 ビットを使用するように画像を変換する場合、合計 16 レベルの赤があります。それらは、R=0、R=17、R=34、... R=255 です。したがって、GAP は 17 になります。

于 2010-12-14T17:54:44.763 に答える
2

解決策が見つかりましたlevels。目的の画像に必要な色の量でありd、除数です (これは、(paint.net クラスを使用する) 私のコードから GetPixel と SetPixel を使用した単純なビットマップ編集に正規化されています)

    private void ProcessDither(int levels, int d, Bitmap image)
    {
        levels -= 1;
        double scale = (1.0 / 255d);
        int t, l;

        for ( int y = rect.Top; y < rect.Bottom; y++ )
        {
            for ( int x = rect.Left; x < rect.Right; x++)
            {
                Color cp = image.GetPixel(x, y);

                int threshold = matrix[y % rows][x % cols];

                t = (int)(scale * cp.R * (levels * d + 1));
                l = t / d;
                t = t - l * d;
                cp.R = Clamp(((l + (t >= threshold ? 1 : 0)) * 255 / levels));

                t = (int)(scale * cp.G * (levels * d + 1));
                l = t / d;
                t = t - l * d;
                cp.G = Clamp(((l + (t >= threshold ? 1 : 0)) * 255 / levels));

                t = (int)(scale * cp.B * (levels * d + 1));
                l = t / d;
                t = t - l * d;
                cp.B = Clamp(((l + (t >= threshold ? 1 : 0)) * 255 / levels));

                image.SetPixel(x, y, cp);
            }
        }
    }

    private byte Clamp(int val)
    {
        return (byte)(val < 0 ? 0 : val > 255 ? 255 : val);
    }
于 2011-01-14T17:04:25.327 に答える