ディザ法 – AS3.0

新聞は基本的に黒インクのみを用いて印刷されています。
そのため使える色は白と黒だけのはずですが、記事中の写真などではグレーの色も確認できます。
実際に写真部分をよく見てもらえるとわかると思いますが、グレーの部分では網目状の点で構成されています。
このように実際に使用している色は少なくても、その密度を変化させることによって多くの色を使っていると見せかけることができ、これを疑似階調表現といいます。

疑似階調表現を実現する方法としてディザ法と呼ばれる方法があり、組織的(Ordered)ディザランダム(Random)ディザの2つがあります。
どちらも使用する色をある密度で配置することによって中間色を作り出します。
この配置をどのように作りだすかによっていくつかのバリエーションがあるんですが、今回はベイヤーパターンと呼ばれる配置を使います。ベイヤーパターンは組織的ディザとして一般的に使われるパターンで、たすき掛けの要領で閾値を設定していきます。
・ベイヤーパターン
1 3
4 2

この基本パターンを再帰的に適用することで大きなパターンを作っていきます。
・4×4 ベイヤーパターン
1 9 3 11
13 5 15 7
4 12 2 10
16 8 14 6

次はランダムディザです。
これは階調を表現するための密度を確率として考え、乱数によって画素値を決める方法です。
例えば輝度値64の場合は64/256=1/4の確率で黒を使い、それ以外は白を使います。
こうすることで輝度値64の領域では白:黒=1:3となりグレーを擬似的に表現できます。

ここでは256階調から2階調に落とします。
ActionScriptによる例は以下のとおりです。(IplImageクラスを使います)

// 組織的ディザ (ベイヤーパターン), 実際にはRGB2階調 = 8色になる
private function bayerDither(img:IplImage):void {
  var r:int = 0, g:int = 0, b:int = 0;
  var adr:int = 0;
  var pattern:Vector.<int> = Vector.<int>([1,9,3,11, 13,5,15,7, 4,12,2,10, 16,8,14,6]);
  
  for(var y:int=0;y<img.height;y++){
    for(var x:int=0;x<img.width;x++){
      adr = (x%4)+(y%4)*4;
      r = ((img.imageData[img.widthStep*y + x*4 + 1]/16) < pattern[adr]) ? 0 : 0xff;
      g = ((img.imageData[img.widthStep*y + x*4 + 2]/16) < pattern[adr]) ? 0 : 0xff;
      b = ((img.imageData[img.widthStep*y + x*4 + 3]/16) < pattern[adr]) ? 0 : 0xff;
      img.imageData[img.widthStep*y + x*4 + 1] = r;
      img.imageData[img.widthStep*y + x*4 + 2] = g;
      img.imageData[img.widthStep*y + x*4 + 3] = b;
    }
  }
}

// ランダムディザ
private function randomDither(img:IplImage):void {
  var r:int = 0, g:int = 0, b:int = 0, gray:int = 0;
  var th:int = 0;
  var len:int = img.imageData.length;
  
  for(var n:int=0;n<len;n+=4){
    gray = (img.imageData[n+1]*77 + img.imageData[n+2]*151 + img.imageData[n+3]*28)/256;
    th = (Math.random()*0xfff)%256;
    if(gray<th){
      img.imageData[n+1] = 0;
      img.imageData[n+2] = 0;
      img.imageData[n+3] = 0;
    }else{
      img.imageData[n+1] = 0xff;
      img.imageData[n+2] = 0xff;
      img.imageData[n+3] = 0xff;
    }
  }
}

・実行結果

(Flashが表示されない人はこちら→Dither.swf)

2つの手法でかなり違いが出ていますね。組織的ディザではパターンがくっきりと表れています。
これをカラー画像にも適用してみます。

(Flashが表示されない人はこちら→Dither2.swf)
(×上:元画像 ○左:元画像)

RGB各上位4ビットを取り16階調と見なしてから、ディザを掛けて2階調に落としています。
16×16のベイヤーパターンを作るのが面倒だったので;
右クリックから拡大して見てみると8色しか使われていないのがよく分かると思います。

この手法はカラー画像を1画素24ビットから3ビットにデータ量を削減することができます。
ただ、表示用にBitmapDataに変換しますから意味はありません。(setPixels()がARGB32ビット固定なため)
効果のひとつとして覚えておくということで。

関連記事:
VTR調変換 – AS3.0
ByteArrayで画像処理入門
cv/im タグ

あわせて読む:

One thought

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です