ディザリング
Dithering別名:ディザ
概要
使える色の数が少ないとき、近い色の点を細かく混ぜて並べ、離れて見たときに中間の色に見せる手法。色を減らしたときに出る縞(バンディング)を、細かい点の模様に置き換える。
デモ
使われる場面
色数の限られた画像への変換
256 色までしか持てない画像形式や、表示できる色の少ない機器に、写真やグラデーションを変換する。
ドット絵やレトロ風の表現
色数を絞ったパレットで、規則的なディザの模様をあえて見せ、中間色や質感を表す。
暗いグラデーションの縞消し
3D の空、霧、暗い部屋のグラデーションは、1 チャンネル 8 ビットでも縞が見えることがある。出力の直前にごく弱いノイズを足して縞を散らす。
印刷や電子ペーパー
インクの有無や白黒の二値しか出せない装置で、点の密度によって濃淡を表す。考え方は同じである。
判断基準
| こういうとき | こうする |
|---|---|
| 色や階調を減らしたら、グラデーションに縞が出た | ディザをかける。丸める前に画素ごとの小さなずれを足し、縞を細かい点に置き換える。 |
| 動く映像やアニメーションに使う | 規則的なディザか、位置で決まる固定のノイズを使う。誤差拡散は、画像のわずかな変化で模様全体が組み変わり、ちらついて見える。 |
| 静止画で、見た目の自然さを優先したい | 誤差拡散を使う。模様が規則的に見えにくく、細部も残りやすい。 |
| GPU のシェーダーで行いたい | 規則的なディザかノイズを使う。画素ごとに独立して計算できる。誤差拡散は前の画素の結果を待つ必要があり、並列に処理しにくい。 |
| あとで拡大や縮小をする画像 | 最終的な大きさにしてからディザをかける。ディザの点は拡大縮小で補間されると、濁りやモアレになる。 |
こう見えたら
指示の例
空のグラデーションに縞が見える。出力の直前に弱いディザを入れて、縞を散らして
色数を減らしたドット絵風の画像で、グラデーションが帯になっている。規則的なディザ(Bayer)で中間色を表して
動画にしたら、ディザの点の模様がちらつく。誤差拡散をやめて、規則的なディザにして
詳細
色を減らすと縞が出る理由
1 チャンネルあたり 段しか使えない場合、なめらかな値 (0〜1)は、もっとも近い段に丸められる。
グラデーションでは、近い値が広い範囲で同じ段に丸められ、境目で一段ずつ飛ぶ。その結果、なめらかだったはずの面に帯状の段差が見える。この縞をバンディングと呼ぶ。
ディザリングは、丸める前に画素ごとに異なる小さなずれを足す。同じ値の領域でも、ずれによって上の段に丸められる画素と下の段に丸められる画素が混ざる。その割合は元の値が上の段にどれだけ近いかで決まるので、少し離れて見ると、点の混ざり具合が中間の色に見える。縞という目立つ誤差を、細かい点という目立ちにくい誤差に置き換えているわけである。
規則的なディザと誤差拡散
規則的なディザは、しきい値の表(Bayer 行列)を画面に敷き詰め、その値をずれとして足す。表の値 を 0〜1 に正規化すると、次の式になる。
画素ごとに独立して計算できるので、シェーダーで扱いやすい。表の模様が格子状の点として見えるのが特徴である。
誤差拡散は、画素を順に丸め、丸めたときの誤差 を、まだ処理していない右と下の画素に配る。よく使われる配り方(Floyd–Steinberg)では、右に 、左下に 、下に 、右下に を足す。誤差が周りで打ち消し合うので、広い範囲で見た平均の明るさが元の画像に近くなる。
// 規則的なディザ。bayer は 0〜1 に正規化した 8×8 のしきい値の表
float b = texelFetch(bayer, ivec2(gl_FragCoord.xy) % 8, 0).r;
vec3 c = color + (b - 0.5) / (levels - 1.0);
outColor = vec4(round(c * (levels - 1.0)) / (levels - 1.0), 1.0);
見分け方と落とし穴
拡大すると、手法ごとの模様がわかる。規則的なディザは十字や格子の模様、誤差拡散は不規則でやや虫の這ったような模様、ランダムなディザはざらついた砂のような模様になる。
ディザは、あくまで離れて見たときに平均がそろって見えるための方法である。点が大きく見える拡大表示や、細部を見せたい文字や線には向かない。また、点の模様は細かい変化の多い画像になるので、画像ファイルに保存すると、ディザをかけない場合より圧縮が効きにくくなることがある。