RIGHT:寄稿:東條遼平 * 2値でグラデーションを表現 [#m4aef391] ハーフトーン処理とは黒と白つまり輝度が0と255の色だけを用いてハーフトーン(中間色)を表現しようという技術で、2値しか出力できない表示装置でなんとかグレースケールを表現しようとしたものです。具体的には目の錯覚というか、点の密度が大きいところは濃く見え、小さいところは薄く見える事を利用しています。 ディザ法とはハーフトーン処理の技術の1つで、グレースケールの画像を小さいブロックに分割し、それにマスクを掛けて閾値を越えたピクセルを白、下回ったものを黒というように処理しています。ディザ法において閾値のパターンはいろいろあり、分割するブロックの大きさもいろいろあるようですが、今回4×4のブロックに分け、Bayer型のパターンを使う事にします。 #ref(img44.png,nolink) 4×4のマス目の中に0から15までの値があります。また、画像の方も4×4のブロックに分割しているので、全く同じ大きさです。ですから対応するパターンを閾値と考えます。ただし、輝度は256階調なのでそれに合わせるためにパターンの値を16倍して8を足します。例えば4×4のブロックのピクセルが全て128だったとしたら次のようになります。 #ref(img45.png,nolink) 以上がディザ法の説明ですが、実装するにあたって実際に画像を分割する必要はありません。 x、yそれぞれの座標を4で割った余りが比較すべきパターンの座標と考えれば良いです。例えば(34, 133)の座標であれば4で割ったあまりは(2, 1)ですので14に対応します。それではソースコードを見てみます。 int bayerpattern[] = { 0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5}; int i, j; for(i=0; i<img->height; i++){ for(j=0; j<img->width; j++){ if((bayerpattern[(i%4)*4 + (j%4)]*16 + 8) <= img->rgb[i*img->width + j].r){ img->rgb[i*img->width + j].r = img->rgb[i*img->width + j].g = img->rgb[i*img->width + j].b = 255; }else{ img->rgb[i*img->width + j].r = img->rgb[i*img->width + j].g = img->rgb[i*img->width + j].b = 0; } } } 比較しているだけなので、特に難しいところは無いと思います。 ディザ法の説明は以上ですが、グレースケールではなくカラー画像に対してディザ法を適用すると面白い結果が得られます。RGBそれぞれに対してハーフトーン処理を行うと、RGBそれぞれの値は0か255しか取らないので、 2×2×2で合計8色しか使っていないにも関わらず、意外と質は低下しません。これを利用してフルカラー画像を8色に減色することができます。減色を行うことでそれまで1ピクセルを24ビットで表していたのが、 3ビットで表現できるようになり、画像のサイズを小さくすることができます。ただし、本プログラムではビット数は減らしていないため、残念ながらサイズは小さくなりません。 - &ref(main.c); - &ref(bitmap.c); - &ref(bitmap.h);