⚠️ これは 非公式の翻訳サイトです。ImageMagick Studio LLC とは無関係です。正確な情報は 原文(https://usage.imagemagick.org/quantize/index.html) を参照してください。

ImageMagick 使用例 -- 色の量子化とディザリング

ImageMagick 使用例 まえがきと索引
減色の概要 (何が関係しているか)
画像内の色 (画像がどんな色を使っているか)

色数を減らしたり特定の色を置き換えたりすることは、画像処理において非常に複雑で難しいステップであり、それがこの例題ページで扱うテーマです。これには、どの色を使うかの決定(色の量子化)と、それらの色を画像上にどう配置するか(ディザリングおよびパターン化)が含まれます。また、ビットマップや 2 色画像の生成、さらにはブール値(オン/オフ)の透明度の取り扱いも含まれます。これは非常に重要であり、色の減色や量子化はしばしば自動的に裏側で行われます。それは ImageMagick がもともとの主要な仕事である、ある画像ファイル形式から GIF、XPixmap、XBitmap のような色数の少ない別のファイル形式へ画像を変換するという作業を遂行できるようにするためです。この仕組みを知っておくことで、プロセスをより細かく制御し、特定の画像ファイル形式に保存される結果の画像を改善することができます。


減色の概要

減色は ImageMagick の非常に重要な側面です。たとえば、数百万色を含む JPEG や PNG の画像を、最大 256 色の GIF 画像に変換するには、効率的かつ効果的な方法で色を減らせる必要があります。画像形式の変換中、これはしばしば自動的に裏側で行われますが、手動で行いたいときもあります。画像内の色数を減らすことは、通常 3 ステップのプロセスです。

  1. まず通常、画像が使っている色を調査する必要があります。実際に何色使われているかだけでなく、特定の色がどれくらいの頻度で使われているかも調べます。ある特定の色を残しても、その色を使っているピクセルが 1 つしかないなら意味がありません。とはいえ、それでもそうする必要がある場合もあります。
  2. 次に、画像を制限したい最終的な色のセットを何らかの形で決める必要があります。特定の画像に対して IM に「最良の」色のセットを決めさせたいかもしれません。あるいは、どんな画像にも使えるもっと一般的・包括的なものが欲しいときもあります。さらには、使われる色のセットから特定の色を加えたり取り除いたりしたいこともあります。
  3. そして最後に、選んだ色だけを使うように画像を変更する必要があります。できれば結果が見栄えよくなるようにしたいでしょうし、あるいは圧縮、比較、最適化がうまくいくようにしたいかもしれません。

さらに事態を複雑にするのは、これらのステップがしばしば相互に関連していることです。というのも、ある色の置き換え手法は、特定の色のセットでしか適用できないことが多いからです。また、特定の色のセットを使う場合は、何らかの色の調査は不要であったり、あるいは特定の色について例外を設ける必要があったりします。基本的に、減色はしばしば自動的に裏側で処理されますが、少なくとも何が起きているのか、そしてその効果がどうなるのかを知っておくのは良いことです。

色の調査

これはおそらく最も重要度が低く、IM は調査を行う手法を提供してはいるものの、減色を目的としてユーザーがこれを行うことはめったにありません。これ以上の議論は関連する節、画像の色の抽出に譲ります。

色の選択(量子化)

良い概説については Wikipedia, Color Quantization を参照してください。色を選択する基本的な手法は 4 つあります。これら 4 つの色制御手法、量子化定義済みカラーマップ均一な色しきい値は、いずれも後で見るように限界を持っています。それぞれの手法の例をここに示します…

  magick colorwheel.png +dither    -colors 32          color_quantize.gif
  magick colorwheel.png +dither -remap colortable.gif  color_predefined.gif
  magick colorwheel.png +dither   -posterize 3         color_uniform.gif
  magick colorwheel.png \
                  -separate -threshold 50% -combine     color_threshold.gif

[IM Output] [IM Output] [IM Output] [IM Output] [IM Output]

最終的な各画像の色数は代表的なセットにすぎませんが、おおよそそれぞれ 32 色です(8 色しかないしきい値処理を除く)。これを見ると、それぞれの手法から何が期待できるかの感触がつかめます。最初の手法以外はすべて、減色される画像とは無関係に、(オペレータの引数に応じた)固定された色のセットを持ちます。実際に現在の画像内容に基づいて色を選ぶのは、最初の手法("[-colors](https://imagemagick.org/command-line-options/#colors)")だけです。テスト画像はほとんどが白なので、多くの明るい色が選ばれています。これは「適応的空間分割(Adaptive Spatial Subdivision)」として知られるオクトツリーを使った技法で画像内の色を調査します。そして与えられた制限の範囲内で、特定の画像に最もよく合う色のセットを選ぼうとします。下記の色の量子化オペレータを参照してください。"[-remap](https://imagemagick.org/command-line-options/#remap)"は、独自の定義済みの色のセットを IM に与えることができます(下記のユーザー定義カラーマップを参照)。上記で使われているカラーマップ "[colortable.gif](../static/img/images/colortable.gif)" は、古い X Window アイコンライブラリで使うために特別に選ばれた 32 色のセットで、漫画のようなアイコンを念頭に設計されています(詳細は AIcon Library, X Icon Color Selection を参照)。"[-posterize](https://imagemagick.org/command-line-options/#posterize)"を使うと、各カラーチャンネルを数学的に一定の色レベルや強度のセットに分割し、'均一なカラーマップ'を生成することもできます。つまり、各チャンネルが一定の値や強度のセットに設定されたカラーマップです。そして最後に、画像のすべて、または特定のカラーチャンネルを"[-threshold](https://imagemagick.org/command-line-options/#threshold)"処理し、本質的に各カラーチャンネルを純粋にブール値、つまりオン/オフにすることができます。すなわち、各カラーチャンネルにゼロまたは MaxRGB(IM の 'Q' レベルに依存)の値を与えます。ただし、これはおよそ 8 色という最小限の色セットしか生成しません。非常に限られた色セットです。しきい値処理は、2 色を選ぶ "[-posterize](https://imagemagick.org/command-line-options/#posterize)" レベル '1' と同等でもあります。

色のセットの適用

色のセットができたら、次の問題は、既存の色が選択した色のセットで置き換えられるように、その色を画像に適用することです。これは'ディザリング'として知られています。「これを選ぶべきか、それともあれを選ぶべきか?」という二者択一的な性質ゆえにそう名づけられました。基本的にディザリングの考え方は、異なる色のピクセルを互いに近くに配置することで、画像内で実際に使われているよりも多くの色が見えていると目を錯覚させることです。つまり、人間の目が隣接する色を'混ぜ合わせる'仕組みのおかげで、その画像領域の色が元の画像の色により近く見えるのです。ディザリングの最良の入門のひとつは Wikipedia にありますが、冒頭の'オーディオディザリング'の節は飛ばす必要があります。これは、限られた色のセットしかないときに、ディザされたピクセルのパターンを使う利点を示す優れた例のセットを提示しています。色を置き換える基本的なスタイルには次のものがあります…

  • 直接的な色マッピング(しきい値処理とポスタライズ)
  • ランダムディザ(完全にランダムなピクセル配置)
  • 誤差補正ディザ(擬似ランダム化されたピクセルのパターン)
  • 整列拡散ピクセルディザ(規則的なピクセルのパターン)
  • デジタルハーフトーン(異なるサイズのドット)

直接マッピングは、上で示したように、与えられたセットの中で最も近い色を選ぶものです。基本的に、変化しない単色の領域がはっきりと得られます。これが、現実の空の写真のような色が徐々に変化する画像に適用されると、画像全体に色の帯が生じます。とりわけ、空の領域のような本来なら滑らかな色のグラデーションになるはずの部分で顕著です。その結果は一般にあまり良くないとみなされます。直接的な色マッピングが許容できると考えられるのは、通常ロゴ、シンボル、アイコン、漫画のような画像の場合だけです。実際には、これが選択肢になることはめったにありません。これが、画像内の色を直接マッピングしたくない場合に、通常のディザリング手法を無効にしなければならない理由です。しかしディザにはディザ自身の問題があります。いったん画像がディザされると、色のパターンが画像の一部になります。そうしたパターンがいったん存在すると、それを取り除くのは極めて困難です。また、画像にディザリングを複数回再適用するのは一般に悪い考えです。それは画像を劣化させるだけだからです。このため、以下の量子化の例のほとんどでは、各手法についてディザされていないバージョンの作り方を一般的に示します。これは、ディザがその情報を隠してしまう前に、どんな色の選択が行われているかを見られるようにするためです。ランダムディザリングは、生み出された中で最も単純なディザリング手法です。また、考えうる中で最悪のディザリング手法ともみなされています。しかし、特別な用途があります。IM の中では 2 色でしか機能しないため、通常は特殊なビットマップディザリングに限定されます。詳しくは下記のしきい値処理によるランダムディザを参照してください。誤差補正ディザリングは、画像全体にわたって色をディザリングする最良の一般的手法とみなされています。画像内の領域の元の色に最も近い近似を生み出すからです。また、現在のところ_任意の_色のセットをディザできる唯一の手法でもあり、そのため 4 つの減色技法すべてに使えます。詳しくは下記のE-Dither の仕組みを参照してください。しかし誤差補正ディザリングには、とりわけ画像のアニメーションに関して、深刻な問題があります。最後の 2 つのディザリング技法、整列拡散ピクセルデジタルハーフトーンもまた良い手法とみなされ、アニメーションにうまく機能しますが、現在のところ任意の色のセットは使えず、固定された均一な色のセットしか使えません。これらはパターンを使って画像を着色する手段を提供し、ほかでは簡単に作れない興味深い効果を生み出せます。
これらの減色のすべての側面は重要な技法であり、理解することで、IM が提供する一般化されたデフォルトを超えて、画像操作の結果を改善できます。学ぶ価値は大いにあります。


画像内の色

使われている色数や全体的な広がりといった画像に関する情報は、最良の技法を判断しようとするプログラムやスクリプトにとって非常に重要です。ここでは、減色に限らず、この種の情報を判断するために使えるいくつかの手法を見ていきます。

画像の色の抽出

カラーテーブルの抽出

詳細な "[identify](basics.html#identify)" を使って画像からカラーパレットを抽出します。次のいずれの方法も使えますが、基本的にどれもまったく同じことを行います。

  magick identify -verbose  image.png
  magick image.png miff:- | identify -verbose -
  magick image.png  -verbose -identify null:
  magick image.png  -verbose info:

| 上記いずれかの詳細な識別の出力は、色数が 1024 を超える場合、カラーテーブルやヒストグラムを返しません! そのため、大きくて色数の多い画像ではこれは当たるか外れるかの賭けであり、おすすめできません。とはいえ、依然として役立つことはあります。
---|---
しかしより良い方法は、画像の "[histogram:](files.html#histogram)" を生成し、その結果に含まれるコメントを抽出することです。 | |

  magick tree.gif  -format %c  -depth 8  histogram:info:-

[IM Output]
| [IM Text]


| "info:" 出力形式は IM v6.2.4 で追加されました。これより前の IM バージョンでは次を使ってください… |

  magick tree.gif histogram:- | identify -depth 8 -format %c -

これらの手法の問題は、色のプレーンテキスト出力が得られるため、自分の用途に合わせてそれを解析する必要があることです。しかし IM v6.2.8-8 以降、"[-unique-colors](https://imagemagick.org/command-line-options/#unique-colors)" オペレータは、元の画像で見つかった一意な色ごとに 1 ピクセルだけを含む小さな画像に変換し、すべてを 1 行に並べます。これにより、画像を、存在する各色を列挙したよりシンプルなカラーテーブル画像に変換できます。画像の幅が色数を返し、実際に色を列挙する必要があれば、"[txt:](files.html#txt)" 画像形式に出力できます。たとえば、これが tree 画像のカラーテーブルです。 |

  magick tree.gif -unique-colors -scale 1000%  tree_colors.gif
  magick tree.gif -unique-colors -depth 16  txt:-

[IM Output]

[IM Text]

この縮小されたカラーテーブルは、生成された色のカラーマップを非常に小さなファイルに保存する方法としても非常に重要です。そうしたマップは、"[-remap](https://imagemagick.org/command-line-options/#remap)" 減色オペレータにとってとりわけ重要です(下記の定義済みカラーマップを参照)。画像内の色だけでなく色数も含む画像を得たい場合は、IM フォーラムの議論から発展した、次のような色ヒストグラムの解決策があります。

  magick rose: -colors 256 -format %c histogram:info:- |
    sed 's/:.*#/ #/' |
      while read count color colorname; do
        magick -size 1x$count xc:$color miff:-
      done |
        magick - -alpha set -gravity south -background none +append \
                unique_color_histogram.png

[IM Output] [IM Output]

組み込みの "rose:" 画像は 3020 色の一意な色を含んでおり、それは長い時間がかかり非常に長い画像を生成してしまうため、ここでは画像を減色する必要がありました。上に示した rose の GIF 画像は同じ減色のセットを含んでいます。結果の画像は依然として同じ数のピクセルを含んでいますが、余分な透明ピクセルでパディングされており、見てのとおり緑がかった灰色、強い赤、そして純白の非常に強いピークが優勢であることがわかります。これは最良の一般的な色ヒストグラム手法ではないかもしれませんが、この画像にはうまく機能します。 "[histogram:](files.html#histogram)" と "[-unique-colors](https://imagemagick.org/command-line-options/#unique-colors)" オペレータの両方とも、色の順序は未定義ですが、赤、次に緑、最後に青のチャンネル値でソートされているように見えます。これは特定の画像にとって最良の方法ではないかもしれませんが、3 次元の色を 1 次元の順序に一般的にソートすることは不可能です。

平均色の抽出

画像の平均色は、"[-scale](https://imagemagick.org/command-line-options/#scale)" を使って画像を 1 ピクセルに縮小することで、非常に素早く求められます。たとえば、これが組み込みの "rose:" 画像の平均色です。色は FX エスケープ形式を使って出力しており、これは変更せずに直接 IM で使える色文字列を返します。

  magick rose: -scale 1x1\! -format '%[pixel:s]' info:-

[IM Text]

"%[pixel:...]" の FX エスケープを使う問題は、RGB 値の代わりに 'white' や 'silver' のような色名を返すことがある点です。しかし、望むビット深度で実際の RGB 値を返す 3 つの FX エスケープを使って、これをシミュレートできます。たとえば…

  magick rose: -scale 1x1\! \
     -format '%[fx:int(255*r+.5)],%[fx:int(255*g+.5)],%[fx:int(255*b+.5)]' info:-

[IM Text]

IM v6.3.9 以降、詳細な "[identify](basics.html#identify)" や "[info:](files.html#info)" の出力を解析せずに、画像に関するより具体的な情報を抽出するのに役立つ新しい "[-format](https://imagemagick.org/command-line-options/#format)" エスケープがいくつかあります。たとえば、画像の赤チャンネル画像から '%[mean]' グレースケール値を取得することで、平均の赤チャンネル色を得られます。

  magick rose: -channel R -separate -format '%[mean]' info:

[IM Text]

特定の色の抽出

コマンドラインから画像の特定のピクセルの色を抽出するには、基本的に 2 つの方法があります。1 つは、特定のピクセル位置に対して "%[pixel:...]" や "%[fx:...]" のような FX エスケープ(上記参照)を使う方法です…

  magick rose: -format '%[pixel:p{40,30}]' info:-

[IM Text]

あるいは、"[-crop](https://imagemagick.org/command-line-options/#crop)" を使って、興味のある単一のピクセルを切り出して画像を単純化し、これまでの手法のいずれかを使うこともできます。たとえば…

  magick rose: -crop 1x1+40+30 -depth 8 txt:-

[IM Text]

特定の(または近い)色のカウント

これは、特定の色のピクセル数や割合を取得するのに使えます。やり方は、その色でないものをすべて黒にし、その色を白にすることです。たとえば、'tree' 画像の "yellow" の太陽の色数を取得してみましょう。

  magick tree.gif -fill black +opaque yellow \
                   -fill white -opaque yellow \
                   -print "yellow sun pixels = %[fx:w*h*mean]\n"   null:

[IM Text]

1 つ注意点があります。テスト対象の色が黒そのものである場合、これは機能しません。黒(または非常に暗い色)を扱うには、fill を入れ替えて、黒でない色を白にマッピングし、その結果をネガ化してすべての黒ピクセルの白いマスクを生成します。"[-print](https://imagemagick.org/command-line-options/#print)" オプションは "-format ... -write info:" を使うのと同等で、画像処理の中のどこででも使えることを覚えておいてください。その後、特殊な "[null:](files.html#null)" ファイル形式を使って不要な画像を捨てました。後の作業でマスクとして使うために画像を保存することもできます。これは小さな画像にはうまく機能しますが、(高解像度のデジタル写真のような)はるかに大きな画像では、'mean' は正確なピクセル数を得るのに十分な精度ではありません! 基本的に上記の 'mean' の使用は比率を生成するのには適していますが、正確なピクセル数には向きません。正確なピクセル数を得るには、正確なピクセル数を持つヒストグラムの 'コメント' 出力を使う方がよいです(上記参照)。上記は、"[-opaque](https://imagemagick.org/command-line-options/#opaque)" オペレータの前にファズ係数オプション "[-fuzz](https://imagemagick.org/command-line-options/#fuzz)" を使って、'近い' 色も指定することもできます。

2 つの色の比較

特定の 2 つの色があり、それらを比較したいとします。"magick compare " を使って RMSE(標準誤差について)を取得できます…

  magick compare -metric RMSE xc:Navy xc:blue null:

[IM Text]

これは、2 つの色の間の距離を、値としても、また黒から白までの距離の正規化されたパーセンテージとしても取得できる点で優れています。しかし、この方法は透明度を適切に扱えません。たとえば、'完全に透明な黒' 対 '完全に透明な白' を比較する場合です。

  magick compare -metric RMSE xc:'#0000' xc:'#FFF0' null:

[IM Text]

透明な色は、実際には距離がゼロであるべきです。完全に透明であれば、その下にある色がどうであれ同じだからです。ところが、得られたのは 4 次元の超立方体の距離です。そのため、上記の色距離の手法は、完全に不透明な色を比較する場合にのみ適しています。
実際の距離を取得するのではなく、ファズ係数 を使って 2 つの色が近いかどうかを確認することもできます。

  magick compare -fuzz 20% -metric AE xc:Navy xc:Blue null:
  magick compare -fuzz 30% -metric AE xc:Navy xc:Blue null:

[IM Text]

ただし、ピクセルが一致しない場合(エラーピクセルの数)、結果は '1' になることを覚えておいてください。値を隔てる実際の 'ファズ' 係数の距離を取得するには、'FUZZ' メトリックを使えます。

  magick compare -metric FUZZ xc:Navy xc:Blue null:

[IM Text]

'正規化された' 値は、実際の距離が 28.7% であることを示しています。ファズ係数を使うことは、透明度が関係する場合の RMSE の計算とは異なります。つまり、ファズ係数は、任意の 2 つの完全に透明な色が等しいものとして扱われるように設計されているからです。そのため、'完全に透明な黒' と '完全に透明な白' は完全に等価です(値 0、つまりエラーピクセルなしを生成します)…

  magick compare -metric FUZZ xc:'#0000' xc:'#FFF0' null:

[IM Text]

色を比較するもう 1 つの方法は、適切なファズ係数のパーセンテージで色を置き換えてみることです。たとえば…

  magick xc:Navy  -fuzz 20% -fill Blue -opaque Blue txt:

[IM Text]

'Navy' が 'Blue' に変化しなかったので、'Blue' との違いは 20% より大きいことになります。一方で

  magick xc:Navy  -fuzz 30% -fill Blue -opaque Blue txt:

[IM Text]

こちらは色が 'Blue' に変化したので、'Navy' と 'Blue' は互いに 20% から 30% の間の距離にあることがわかりました。スクリプトでこれを行うには、次のようなものを使います…

  fuzz=%1
  color1="red"
  color2="#e00"

  color2=`magick xc:"$color2" -format '%[pixel:s]' info:`
  result=`magick xc:"$color1" -alpha set -channel RGBA -fuzz $fuzz \
            -fill $color2 -opaque $color2 -format '%[pixel:s]' info:`
  if [ "$result" = "$color2" ]; then
    echo "Colors match according to Fuzz Factor"
  else
    echo "Colors DO NOT match"
  fi

特殊なオプション "-alpha set -channel RGBA" は、透明および透明に近い色のファジーマッチングを可能にするために重要です。


色の量子化

色の量子化オペレータ

色の量子化の主役であり、すべての自動減色で内部的に使われているのが、"[-colors](https://imagemagick.org/command-line-options/#colors)" オペレータです。これは「適応的空間分割(Adaptive Spatial Subdivision)」減色アルゴリズムを実装しており、非常に優れた減色アルゴリズムです。典型的な例を示します。多くの色を含む 'colorwheel' 画像があり、さまざまなディザ手法を使って、色数を 64 色だけに減らすよう IM に指示します。

  magick colorwheel.png  -dither None       -colors 64  colors_64_no.gif
  magick colorwheel.png  -dither Riemersma  -colors 64  colors_64_rm.gif
  magick colorwheel.png  -dither FloydSteinberg \
                                             -colors 64  colors_64_fs.gif

[IM Output] [IM Output] [IM Output] [IM Output]

IM はデフォルトで、画像全体にわたって色をぼかすために 'ディザ' を使います。これは、滑らかに変化するグラデーションにおける突然の色の変化を防ぎます。ディザリングを無効にすると('None' または "[+dither](https://imagemagick.org/command-line-options/#dither)" 設定を使う)、この特定の画像にとって IM が最良とみなした色のセットを生成するために、どの色が混ぜ合わされたのかがはっきりと見えます。また、ディザリングが行われなかった場合に色のグラデーションが生み出す突然の色の変化も見えます。もちろん、この画像はほとんどの画像が使うよりもはるかに多くの色を使っています。そのため、64 色の制限は多くの画像にとってしばしば許容できるものの、この画像にはまったく許容できません。言い換えれば、色の量子化は特定の画像にとって最良の色のセットを見つけようとします。極めて少数の色を使った、IM ロゴの一部の色の量子化の例を示します。

  magick logo: -resize 40% -crop 100x100+105+50\! -normalize  logo.png
  magick logo.png  +dither             -colors 8  colors_8_no.gif
  magick logo.png  -dither Riemersma   -colors 8  colors_8_rm.gif
  magick logo.png  -dither FloydSteinberg \
                                        -colors 8  colors_8_fs.gif

[IM Output] [IM Output] [IM Output] [IM Output]

これを、組み込みの "rose:" 写真画像のいくつかの結果と比較してください。

  magick rose: +dither             -colors 16 colors_16_no.gif
  magick rose: -dither Riemersma   -colors 16 colors_16_rm.gif
  magick rose: -dither FloydSteinberg \
                                     -colors 16 colors_16_fs.gif

[IM Output] [IM Output] [IM Output] [IM Output]

見てのとおり、漫画のような画像は、まともな結果を生み出すのに、本物の写真よりもはるかに少ない色しか必要としません。 | _現在 IM に実装されている色の量子化アルゴリズムは「適応的空間分割」だけであり、非常にうまく機能するため、ほかのものを追加する必要はほとんどありませんでした。しかし、フィードバックによってこのアルゴリズムは着実に改善されています。

余談: 参考までに、"[Gifsicle](http://www.lcdf.org/gifsicle/)" プログラムは(その "--color-method" オプションを使って)他のいくつかの色の量子化手法を列挙しています。これらの色の量子化手法が IM とどう比較されるのかはわかりません。色の量子化のさまざまな手法について良い参考資料を見つけたら、私にメールしてください。_
---|---

色の量子化の内部

画像で使う限られた数の色を選択するプロセスは色の量子化と呼ばれ、多くの要因が関わる非常に複雑なプロセスです。その完全な技術的説明は ImageMagick の Web サイト Color Reduction Algorithm に記載されています。しかしここでは、そのより重要な側面のいくつかを例で示してみます。おそらく最大の要因は、画像で実際に使われている色です。ある画像にある特定の色を選んでも、その色に'近い'ピクセルがほとんどないなら意味がありません。そのため、色の選択は画像で使われている色だけでなく、その色に'近い'ピクセルの数にも依存します。これは、2 つの異なる 2 色画像を単一の共通の色に減らそうとすることで、かなり簡単に実証できます。

  magick -size 4x1 xc:blue -draw 'fill red   point 0,0' \
                                                -scale 20 colors_rb.gif
  magick -size 4x1 xc:red   -draw 'fill blue point 3,0' \
                                                -scale 20 colors_br.gif
  magick colors_rb.gif  -colors 1  colors_rb2.gif
  magick colors_br.gif  -colors 1  colors_br2.gif

[IM Output] [IM Output]
[IM Output] [IM Output]

見てのとおり、最終的な単一の色は、存在する色だけでなく、画像内の各色の量にも依存します。

  magick -size 20x640  gradient: -rotate 90  gradient.png
  magick gradient.png   +dither  -colors 5   colors_gradient.gif

[IM Output]

色の量子化は、現在のカラースペース内で均一であることに注意してください。

FUTURE: "[-treedepth](https://imagemagick.org/command-line-options/#treedepth)" 設定の効果は正確には何なのか?
知っている人はメールしてください

色の量子化とカラースペース

どの色が選択されるかに対するもう 1 つの大きな影響は、'近い' あるいは '近接した' 色とは正確に何を意味するのかを定義することです。これは、量子化(色の選択)に使われるカラースペースによって定義され、(IM v6.2.8-6 以降)"[-quantize](https://imagemagick.org/command-line-options/#quantize)" カラースペース設定によって制御されます。"[-quantize](https://imagemagick.org/command-line-options/#quantize)" 設定は、極めて少数の色が選ばれるときにとりわけ重要になります。これを実証するために、標準的な 'colorwheel' 画像を、さまざまな異なるカラースペースを使い、異なる '色の距離' を定義しながら減色してみましょう。

  for S in    RGB CMY sRGB GRAY \
              XYZ LAB LUV  \
              HSL HSB HWB  \
              YIQ YUV OHTA ; do \
     magick colorwheel.png   -quantize $S   +dither -colors 16 \
             -fill black -gravity SouthWest -annotate +2+2 $S \
             colors_space_$S.gif; \
  done

[IM Output] [IM Output] [IM Output] [IM Output]
[IM Output] [IM Output] [IM Output]
[IM Output] [IM Output] [IM Output]
[IM Output] [IM Output] [IM Output]

見てのとおり、選ばれる色はカラースペースがどう構成されているかに大きく依存します。sRGB(赤、緑、青)の色立方体は、一般に少なくとも原色に近い色が選ばれる結果になります。sRGB カラースペースは漫画のような画像やアイコンの色を選ぶのにとりわけ優れていますが、実際には一般的な写真のような画像には不向きなカラースペースです。CMY カラースペースは sRGB カラースペースとまったく同じです。sRGB と CMY カラースペースの間で変換するのにカラーチャンネルを単純に反転させるだけだからです。そのため、量子化される色はおおよそ同じ解になります。 | _CMYK カラースペース(図示なし)も、異なる理由で同じものを生成します。内部的に 'K' チャンネルと画像の 'カラーマップ' は同じデータポインタを使う(パレットチャンネルを参照)ため、IM は量子化の前にそれを CMY に戻して変換します。


---|---
sRGB カラースペースは予想どおり RGB と似た結果を生成しますが、カラースペース内の黒に近い色の数を減らすようにゆがめられています。そのため、カラーホイールの中心が選択できる色が少なくなり、より大きな '完全には黒でない' スポットを生成します。XYZ カラースペースもリニア RGB カラースペースに非常によく似ています。ここでの大きな違いは、色軸がシフトされ、私たちが見ることのできる(通常は見ることのできない色さえも)あらゆる可能な色をよりよく含むようになっている点です。そのため、カラーホイール内の色データはもう少し圧縮され、結果として量子化はより広がるように見えます。LAB と LUV のカラースペースは、互いに異なるものの似た色軸に基づいています。その結果、色の量子化の配置が異なります。'色相' チャンネルを含む特殊なカラースペース、たとえば HSL(色相、彩度、明度)、HSB(色相、彩度、輝度)、HWB(色相、白、黒)は、すべてカラースペースの一部として色の循環的なカラーホイール表現を持っています。実際、このカラーホイールを生成するのに使われたのは HSL カラースペースでした。カラーホイールの生成を参照してください。 | _執筆時点では、IM が使う色距離アルゴリズムはカラースペースの '色相' の循環的な性質を考慮していません。このためのアルゴリズムは大きく異なります。このため、'色相' が一周する '赤' の経路に沿って強い不連続が生じ、色の量子化プロセスで赤の色がほとんど選ばれない結果になります。

---|---
YIQ、YUV は、写真や現実世界の画像、とりわけ微妙な色合いや肌の色調にずっと適した、より自然な 'パステル' や '中間調' の色合いを生成するように設計されています。Helmut Dersch は彼の Web サイトで、ゆがみには LAB カラースペースを使うことを検討すべきだと述べています。 | _古いバージョンの IM(具体的には IM バージョン 5)では、量子化に使うカラースペースは "[-colorspace](https://imagemagick.org/command-line-options/#colorspace)" オプションで設定されていました。しかし IM バージョン 6 では、このオペレータは画像がメモリ内にどう格納されるかを変更するのに使われ、そのため色の量子化の設定ではありません。

そのため IM v6.2.8-6 では、この仕事をするために "[-quantize](https://imagemagick.org/command-line-options/#quantize)" 設定が提供されました。ただし、これは "[-colors](https://imagemagick.org/command-line-options/#colors)"、つまり色の量子化プロセスのための設定にすぎません。"[-remap](https://imagemagick.org/command-line-options/#remap)" や "[-posterize](https://imagemagick.org/command-line-options/#posterize)"、あるいはさまざまなディザリング技法による色の置き換えやディザリングには何もしません。_
---|---
利用可能なカラースペースの完全な一覧については、"[-colorspace](https://imagemagick.org/command-line-options/#colorspace)" オペレータを参照してください。色の選択に対するカラースペースの効果のさらなる例は、単色のランダムなスポットの例を見るとわかります。そこでは、さまざまなカラースペースを使って、ランダム化された画像の色数を減らすために色の量子化が使われています。 量子化は色を保存しない上記のすべての画像で、純粋な黒の色は色の量子化によって実際には決して選ばれていないことに注意してください。とはいえ、画像内には純粋な黒のピクセルは 1 つしかなく、いずれにせよ黒に近い色も多くはありません。その結果、最終的な画像に現れる黒は、画像のラベル付けの一部として後から追加されたものだけです。'GRAY' カラースペースの画像でさえ、純粋な黒の色は生成しませんでした。実際、どの画像も、赤、青、緑、シアン、マゼンタといった原色や二次色を一切含んでいません! これの唯一の例外は白です。画像にはかなりの量の純白の色が含まれていたため、それが '優先される色'(下記参照)になったのです。しかし、この状況はバグではありません! まず、上記の例で 'black' の色が一般に選ばれなかったのは、通常、元の画像に黒がほとんどないため、色の量子化が暗い色をあまり気にしなかったからです。実際、画像でより一般的なため、より多くの明るい色を生成しました。具体的な例については前の節を参照してください。第二に、量子化は画像内の既存の色のピクセルの最大数に近い色を選ぼうとするため、これは '純粋な' 原色や二次色に一致させ_ない_ことで最もよく達成されます。これらは使われているカラースペースのまさに両極端に常に位置するからです。'やや外れた色' は '原色' よりも多くの色に一致する傾向があるため、こちらの方がより頻繁に選ばれます。というわけで、はっきり言っておきましょう… 色の量子化(" -colors")は一般に原色を選ぶのを避けます!

IM バージョン 6.3 以降、色の量子化機能は、元の画像で非常に一般的な色を含めようとするように修正されました。そのため、画像が単色の領域(上記の 'white' のような)を含んでいる場合、その色は一般に最終的なカラーマップに含められます。これは、とりわけ '漫画' のような画像や単色背景上の画像で、状況をいくらか改善します。'単色' の色は一般に選ばれ、下記で見るディザの斑点を避ける助けになります。カラーマップに特定の色を含める解決策 現時点では、後のディザリングのために選ばれる色に '特定の色' が確実に含まれるようにする方法はわずかしかありません。1 つの方法は、画像を通常どおり量子化し、その後生成されたカラーマップを出力する("[-unique-colors](https://imagemagick.org/command-line-options/#unique-colors)" を使う)ことです。そうすれば、特定の色が本当にその色になるようにそのカラーマップを調整できます。最後に、Remap Colors オペレータを使って、提供したカラーマップで画像をディザリングできます。そのカラーマップはもはや画像にとって最良の色ではないかもしれませんし、おそらく他のいくつかの色も調整すべきですが、望んだカラーマップに近いものにはなります。あるいは、"[-colors](https://imagemagick.org/command-line-options/#colors)" を使う前に、画像内で保存したい特定の色の大きなパッチを(画像を拡大して)追加する方法もあります。特定の色の大きな '見本' を追加することで、その色が最終的なカラーマップで選ばれる可能性が高くなります(また、他のすべての色も、そのカラーマップによりよく合うように自動的に調整されます)。これがうまくいけば、追加した色の見本は変化しない(ディザされない)はずです。その後、追加した見本を取り除くために画像をクロップできます。うまくいかなくても、IM は少なくとも望んだ '特定の色' に近い色を追加しているはずなので、元の画像に Remap Colors を使う前に、生成されたカラーマップをわずかに調整するだけで済みます。これを試したら、成功・失敗にかかわらず、どうだったか教えてください。 理想的には、最終的なカラーマップの一部でなければならない少数の特定の色を指定し、それから残りのカラーマップの色について、特定の画像にとって最良の色を IM に選ばせる方法があればよいと思っています。

色の量子化と透明度

ImageMagick はデフォルトで、完全に不透明な色を生成するだけでなく、半透明の色も生成しようとします。こうすることで、透明な影やその他のオーバーレイ効果を含む画像が、それらの効果を失わないようにします。しかし IM v6.2.6 では、透明度が関係する色の量子化は、すべての完全に透明な色を同じ色として扱うように修正されました。これは線形の修正なので、半分だけ透明な色も、完全に不透明な場合よりも互いに近いと考えられます。この修正のおかげで、IM の色の量子化は依然として半透明の色を生成しますが、画像内の不透明な色により集中し、完全に透明な色にはあまり集中しなくなります。たとえば、ここでは色の虹のグラデーションを生成し、画像は上端で完全に不透明、上端で完全に透明にしています。画像がどれほど透明かを見られるように、背景パターンの上に画像を表示しています。

  magick xc:red xc:yellow xc:green1 xc:cyan xc:blue \
          +append -filter Cubic -resize 100x100\!  -size 100x100 \
          gradient: -alpha off -compose CopyOpacity -composite alpha_gradient.png
  magick alpha_gradient.png  +dither  -colors 256  alpha_colors_256.png
  magick alpha_gradient.png  +dither  -colors 64   alpha_colors_64.png
  magick alpha_gradient.png  +dither  -colors 15   alpha_colors_15.png

[IM Output] [IM Output] [IM Output] [IM Output]

見てのとおり、この画像が必要とする色数を減らすよう IM に求めると、不透明な色をはるかに多く作り、より半透明な部分にはより透明度の高い色を少なく使いました。その結果、とりわけ色数が非常に少ないときに、選ばれた色の非常に良い広がりが得られます。しかし、上で指摘したとおり、原色が選ばれないだけでなく、まったく同じ理由で完全に透明な色も選ばれません。実際、完全に不透明な色さえ選ばれません! 言い換えれば、前の例で色の量子化された画像のすべての色は半透明です。これをはっきりさせておきましょう。

透明度が関係する場合、IM の色の量子化は
完全に不透明な色も、完全に透明な色さえも選ばないことがあります!

もちろん IM v6.3 以降、そして '共通色' のバグ修正(上記の 量子化は色を保存しない を参照)により、画像が多くの不透明色と完全に透明な色を含む場合(これはよくあることです)、これが起こる可能性は低くなりました。煙や影の効果を含む画像のように、多くの半透明の色を含む画像もあるため、結果の画像に含めるために完全に透明な色が選ばれていることを確認するために、試しに実行してみるとよいかもしれません。そうすれば、最も透明度の高い色を完全に透明にマッピングし、Remap Colors を自分で行うことができます。結果の画像に完全に不透明な色と完全に透明な色の両方を確実に入れたい場合は、アルファチャンネルを正規化またはコントラストストレッチできます。たとえば、ここでは "[-contrast-stretch](https://imagemagick.org/command-line-options/#contrast-stretch)" を使って、主要な色の選択が不透明になるようにしています。とはいえ、これはより一般的な状況にはおそらく少々手荒です。

  magick alpha_gradient.png  +dither  -colors 15 \
          -channel A -contrast-stretch 10%  alpha_colors_15n.png

[IM Output] [IM Output] [IM Output]

これは、半透明の色を許可しない GIF 画像、透明度を許可しない JPG、あるいは適切に保存するのに量子化を必要としない PNG にとっては問題ではありません。これは、多くの半透明の色が関係する画像で減色を強制するような特殊なケースでのみ問題になります。GIF 形式では半透明の色を保存するのは無駄な試みであることを覚えておいてください。そのため、そうした画像形式のために自分で色の量子化を行う予定なら、減色されたカラーセットを生成するときに画像の透明度を無視するよう IM に伝える必要があります。それは、特殊な "[-quantize](https://imagemagick.org/command-line-options/#quantize)" カラースペース設定 'transparent' を使うことで行えます。

  magick alpha_gradient.png -quantize transparent \
                            +dither  -colors 15   alpha_colors_15qt.png

[IM Output] [IM Output]

色の量子化が色の透明度を完全に無視し、画像のアルファチャンネルにまったく手を触れていないことに注目してください。これは、他の色とは完全に別個に、画像にとってより適切な方法でアルファチャンネルを処理できることを意味します。実際、問題なく "[-colors](https://imagemagick.org/command-line-options/#colors)" の前でも後でも行えます。結果に違いはありません。そのため、この量子化カラースペースは、GIF や XPM 画像形式のような、ブール値または透明度なしの形式に保存する予定の画像の色数を減らすときに推奨されます。生成された色の数を数えると、要求した色数とぴったり同じ数が生成されていることもわかります。そのため、(おそらく)完全に透明な色も必要な場合は、画像の最終的なカラーテーブルにそのための空きを残すために、"[-colors](https://imagemagick.org/command-line-options/#colors)" の引数を少なくとも 1 つ減らす必要があります。したがって、GIF ファイル形式の 256 色のカラーテーブル制限を扱うには、色数を 256 ではなく 255 に減らし、"[-transparent-color](https://imagemagick.org/command-line-options/#tranparent-color)" 設定で定義される完全に透明な色のインデックスのための余分な空きを残す必要があります。これはより小さなカラーテーブルサイズに合わせて調整してください。この量子化の振る舞いは、IM が GIF ファイル形式に保存するときには自動ですが、グローバルまたは共有のカラーテーブルを生成する際に自分で量子化を行う必要があるときに重要です。もちろん、半透明のピクセルを、画像に望む見た目に対して正しくなるように、依然として扱う必要があります。

FUTURE: この最後の部分は、おそらく近い将来に作成される 'アルファチャンネルの
ディザリング' に関する新しい節に移動されるでしょう。そしてその節への参照が
ここに追加されます。

画像内の残りのカラーチャンネルに影響を与えずに、アルファチャンネルだけをブール値、つまりオン/オフの設定にディザリングする例をいくつか示します。

  magick alpha_gradient.png \
          -channel A   -threshold 50%       alpha_dither_threshold.gif
  magick alpha_gradient.png \
          -channel A -ordered-dither checks alpha_dither_checks.gif
  magick alpha_gradient.png \
          -channel A -ordered-dither o8x8   alpha_dither_ordered.gif
  magick alpha_gradient.png \
          -channel A -ordered-dither h8x8a  alpha_dither_halftone.gif

  magick alpha_gradient.png -channel RGBA -separate \
          \( +clone -monochrome \) \
          +swap +delete -combine alpha_dither_monochrome.gif
  magick alpha_gradient.png -channel RGBA -separate \
          \( +clone -dither FloydSteinberg -monochrome \) \
          +swap +delete -combine alpha_dither_monochrome_fs.gif
  magick alpha_gradient.png -channel RGBA -separate \
          \( +clone -remap pattern:gray50 \) \
          +swap +delete -combine  alpha_dither_map.gif
  magick alpha_gradient.png -channel RGBA -separate \
          \( +clone -dither FloydSteinberg -remap pattern:gray50 \) \
          +swap +delete -combine  alpha_dither_map_fs.gif

[IM Output] [IM Output] [IM Output] [IM Output]
[IM Output] [IM Output] [IM Output] [IM Output]

| _アルファチャンネルのコピーを "[-monochrome](https://imagemagick.org/command-line-options/#monochrome)" または "[-remap](https://imagemagick.org/command-line-options/#remap)" を使ってディザリングできるようにディザリングするときは、画像が純粋なグレースケール画像であり、透明度を含む形状マスクではないことを確認してください。そうしないと、おそらくアルファチャンネルが依然として存在することによる非線形の効果が生じてしまいます。

画像からアルファチャンネルをグレースケールマスクとして抽出・復元してディザリングできるようにする方法はいくつもあります。上記ではチャンネル分離結合を使ってこれを行っています。ほかの方法では、CopyOpacity 合成とともにアルファ抽出を使います。_
---|---


誤差補正ディザリング

概要で述べたとおり、誤差補正ディザは一般に、減色されたカラーセットで元の画像を最も忠実に表現するための最良の選択肢とみなされています。また、ユーザーが提供したものであれ、IM の色の量子化ルーチンが決定したものであれ、あらかじめ定義された任意のカラーパレットに自身を制限します。このため、これは "[-colors](https://imagemagick.org/command-line-options/#colors)"、"[-remap](https://imagemagick.org/command-line-options/#remap)"、"[-posterize](https://imagemagick.org/command-line-options/#posterize)"、"[-monochrome](https://imagemagick.org/command-line-options/#monochrome)" といった IM オペレータが提供する一般的な減色のための論理的なデフォルト選択肢です。

E-Dither の手法

バージョン 6.4.2-9 以降、IM は "[-dither](https://imagemagick.org/command-line-options/#dither)" 設定で選択できる複数のディザリングスタイルすなわち手法を提供するようになりました。これより前、IM は Riemersma ディザ、すなわち ヒルベルト曲線ディザの変種に限られており、これは "-dither Riemersma" を使って設定できます。今では "-dither FloydSteinberg" を使って Floyd-Steinberg ディザも選べます。お使いの IM のバージョンにどんなディザ手法が実装されているかは、次を使って確認できます…

  magick -list dither

[IM Text]

たとえば、これは異なるディザリング手法を使ってディザされたカラーホイールです。

  magick colorwheel.png -dither Riemersma      -colors 16 dither_riemersma.gif
  magick colorwheel.png -dither FloydSteinberg -colors 16 dither_floyd.gif

[IM Output] [IM Output]

見てのとおり、Floyd-Steinberg ディザは、デフォルトの Riemersma ディザよりもはるかに均一なディザパターンを生成します。両者の最大の違いは、それぞれが '色の誤差' を隣接するピクセル間にどう分配するかです。では、E-Dither がどう機能するのかを見てみましょう。

E-Dither の仕組み

書き換え進行中

一般的なディザリングのために IM が使う具体的な手法は、「ヒルベルト曲線誤差補正ディザ」の変種です。これは実際には非常に優れたディザリング技法で、非常によく定義されており、それなりに高速です。完全な説明(および非常によく似た変種)については、Riemersma ディザを参照してください。基本的に、画像内の各ピクセルは 'ヒルベルト曲線' として知られる非常に複雑な経路で調べられます。ピクセルにはその値に最も近い色が割り当てられ、ピクセルの元の色と選択された色の間の差異は保存され、次のピクセル(常に隣接するピクセル)の色値に加えられてから、再び新しい色が選択されます。こうして、選択された色と画像の元の色との間のあらゆる色の変動が、同じ領域内の他のピクセルに分配されます。その結果、最終的な画像には特定の色だけが割り当てられるものの、その領域の基本的な全体の色は元の画像によく一致します。たとえば、これは小さな灰色の画像で、元の色を含まない色のセットを使ってディザリングするよう IM に求めたものです。割り当てられた個々の色付きピクセルが見えるように、結果の画像は拡大されています。

  magick -size 10x10 xc:'#999999' -scale 80x80  dither_not.gif
  magick -size 10x10 xc:'#999999' \
          -remap colortable.gif   -scale 80x80  dither.gif

[IM Output] [IM Output]

見てのとおり、元の画像の色が指定したカラーマップになかったため、元の色は、与えられたカラーテーブルにあった最も近い 3 色のパターンを使って近似されています。 上記のディザパターンが生成した色を平均すると、色 [IM Text] が得られます。これは画像の元の平均色 [IM Text] に非常に近く、それこそが生成されたディザパターンの目的そのものです。しかし、色を割り当てるのに使われる '経路' は複雑なため(一般には局所的な領域内にとどまりますが)、色の割り当ては本質的にランダムなパターンを生成します。ただし技術的にはランダムではありません。同じ画像は同じパターンを生成するからです。しかし、結果はランダム、あるいは少なくとも擬似ランダムと言ってもよいものです。"F-S" ディザは、実際には 1970 年代初頭に登場して以来開発されてきたいくつかの 'ラスタライズ E-Dither' のうちの 1 つ(最初のもの)にすぎません。また、最良のものとはみなされていないものの、おそらく最も広く実装されています。そうしたアルゴリズムのより完全な要約については、論文 Dithering Algorithms を参照してください。IM v6.4.3 以降、IM でも直接利用でき、画像の上から下へ行ごとに 'サーペンタイン(蛇行)' 経路をたどるように実装されています。

  magick -size 10x10 xc:'#999999'  -dither FloydSteinberg \
          -remap colortable.gif   -scale 80x80  dither_fs.gif

[IM Output] [IM Output]

特に "Floyd-Steinberg ディザ" は、"ヒルベルト曲線ディザ" よりも 'ハッシュ' のようなピクセルのパターンを生成し、実際にそうなるよう設計されました。そうした規則的なパターンは、小さなカラーアイコン画像の低レベルな手作業によるクリーンアップをずっと容易にします。これは私が過去に Anthony's Icon Library のために多く行っていたことですが、その種のことは、おそらく小さなモノクロ画像を除いて、もはやあまり必要とされなくなりました。

E-Dither の問題 - 変化に敏感

誤差補正ディザを使うときに直面する最大の問題の 1 つは、本質的にランダムなピクセルのパターンが得られ、それが変化に対して非常に敏感でもあることです。たとえば、ここでは元の灰色の画像を取り、再びディザリングする前に 1 つのピクセルを別の色に置き換えています。その結果、ヒルベルト曲線ディザがたどる経路の、その先にあるすべてのピクセルでディザパターンが完全にずれてしまいます。

  magick -size 10x10 xc:'#999999' -draw 'fill #C28 point 2,2' \
          -remap colortable.gif   -scale 80x80   dither_modified.gif
  magick compare dither.gif dither_modified.gif dither_difference.gif

[IM Output]
元のディザ | [IM Output]
1 ピクセルの変更 |
| [IM Output]
変化の比較
---|---|---|---

見てのとおり、画像に 1 つのピクセルを加えただけで、ディザパターンが劇的に変化しました! たった 1 ビットの変化で結果の画像は異なるものになります。とはいえ、(拡大していなければ)画像の全体的な見た目は基本的に同じままです(結局のところ、それが良いディザアルゴリズムの目的です)。"magick compare" 画像も、ディザパターンの変化の程度を示しています。この場合、約 80% のピクセルがまったく異なる色を割り当てられました。ヒルベルト曲線ディザでは、1 ピクセルの変更が、それより後に来るすべてのピクセルを異なるものにする可能性があり、ディザパターンの 0% から 100% が異なる可能性があることを意味します。それは、変化が複雑なヒルベルト曲線のどこで起きたかに依存します。一方、Floyd-Steinberg ディザは画像内を一方向にしか進まないため、1 ピクセルの変更は変化点の片側のパターンしか変更しません。

  magick -size 10x10 xc:'#999999' -draw 'fill #C28 point 2,2' \
          -dither FloydSteinberg -remap colortable.gif \
          -scale 80x80   dither_fs_modified.gif
  magick compare dither_fs.gif dither_fs_modified.gif dither_fs_difference.gif

[IM Output]
FS ディザ | [IM Output]
1 ピクセルの変更 |
| [IM Output]
変化の比較
---|---|---|---

見てのとおり、まったく同じ問題を抱えています。1 ピクセルの変更が、そのピクセルより後に処理される画像領域、つまりその行から下のディザパターンをほぼ完全に変化させます。単一の画像にとっては、ディザされた色の結果のパターンは重要ではありません。パターンの平均色が、画像のその領域に適切な色を与えるはずだからです。しかし、ある画像の後に非常によく似た画像が続くアニメーションで、広い領域が一定の色である場合、変化するディザパターンは低レベルの背景 'ノイズ' として非常に目立ち、いらだたしくなります。たとえば、ここでは同じディザ色だが各フレームで 1 ピクセルだけ変更した 3 画像のアニメーションを生成します。この変化するパターンがよりはっきり見えるように、中央の領域も拡大しています。

  magick -size 80x80 xc:'#999999' \
          \( +clone -draw 'fill #C28 point 2,2' \) \
          \( +clone -draw 'fill #28C point 2,2' \) \
          -remap colortable.gif  -set delay 50 -loop 0   dither_anim.gif
  magick dither_anim.gif -crop 10x10+40+40 +repage \
                              -scale 80x80     dither_anim_magnify.gif

[IM Output] [IM Output]

見てのとおり、E-Dither が生み出す擬似ランダム性によって、画像の背景が一種かき回されるような状態になります。ほとんどの場合、使われる色は十分に近いため、この 'ディザノイズ' は見えません。しかし、ディザリングの色が目に見えて異なる場合(この場合はカラーマップの使用によって強制されています)、それは確実に問題になります。この 'ディザノイズ' を示すアニメーションのより実用的な例については、ビデオの色の最適化を参照してください。パターンの変化はアニメーションの最適化にも問題を引き起こします。つまり、パターンが異なると、単純なフレーム最適化がフレームオーバーレイのサイズを縮小できなくなります。1 つの解決策についてはファジー色最適化を参照してください。ただし、これはかき回しが非常によく似た色を使っている場合にのみ機能します。 他のディザリング手法(しきい値整列ディザなど)とは異なり、"[-channel](https://imagemagick.org/command-line-options/#channel)" 設定は色の量子化や誤差補正ディザに影響を与えません。基本的に、これらの画像操作の仕組みの中にはその居場所がないのです。
整列ディザにはこうした問題が一切なく、変化をその変化の直近の局所領域に封じ込めます。残念ながら、整列ディザも一般には数学的に導出された色のセットの使用に限られます(下記の均一なカラーマップを使った整列ディザを参照)。

E-Dither のピクセルの斑点

E-Dither のもう 1 つの問題は、本来ならかなり均一な色になるはずの領域に、時折おかしな色のピクセルを生み出すことがあることです。たとえば、グレースケール画像の中に時折緑のピクセルが現れたり、あるいは下記の例のように、それ以外は無地の平らな青の領域の中に白いピクセルが現れたりします。これは、多数の色を持つオブジェクトと、無地の単色で変化しない他の領域を含む大きな画像でとりわけ起こりがちです。これは、図やドローイングでよく見られるように、平らな色の背景の上に色付きのオブジェクトが重ねられている場合に特に典型的です。上記のテスト例の拡大図でも、小さな 1 ピクセルの変更からかなり離れたところに、余分な薄紫のピクセルが追加されているのが見えます。上記に追加されたおかしな色のピクセルはそれほど目立たず、カラーマップが画像をかなりよくカバーしているため、おかしなピクセルは画像のディザリングに使われる通常の 3 色にそれなりに近いものです。より極端な例として、ここではぼかしたグラデーション背景を用意し、誤差補正ディザに本当に負荷をかけるために、64 色に大幅に減色しました。 |

  magick -size 100x60 xc:SkyBlue \
          -fill DodgerBlue -draw 'circle 50,70 15,35' \
          -fill RoyalBlue  -draw 'circle 50,70 30,45' \
          -blur 0x5  -colors 64     speckle_gradient.gif

[IM Output]
見てのとおり、この大幅に減色されたカラーマップでも、誤差補正ディザは元のグラデーションをそれなりにうまく表現できました。しかし、上記に純白のパッチを加えると… |

  magick -size 100x60 xc:SkyBlue \
          -fill DodgerBlue -draw 'circle 50,70 15,35' \
          -fill RoyalBlue  -draw 'circle 50,70 30,45' -blur 0x5 \
          -fill white -draw 'rectangle 40,40 60,55' \
          -colors 64   speckle_problem.gif

[IM Output]
E-Dither が、それまで何もなかった画像の上部領域に、突然白いピクセルを散りばめ始めたのがわかります。 これらのピクセルをよりはっきり見られるように、小さな部分の拡大図を示します… |

  magick speckle_problem.gif -crop 15x15+75+0 +repage \
          -scale 90x90    speckle_prob_mag.gif

[IM Output]
おかしな色のピクセルは、2 つの要因によって生じます。まず、色の量子化が、画像の最終的なカラーマップに単一の純白の色を(しかし他の白青のアンチエイリアス色は一切含めずに)含めることを強制され、それによってディザリングプロセスがこの余分な色を使えるようになりました。しかし、E-Dither は誤差をゆっくりと累積させていきます。とりわけ上記画像の上部のような、極端な色の領域では顕著です。やがて誤差が、その 1 つの追加色を最も近い一致にするのに十分なほど大きな値にまで積み上がります。そのため、ときどき、擬似ランダムな位置に、'誤差を補正する' ために、コントラストの非常に強い白いピクセルが出力されます。その結果が、白いピクセルの非常に薄い斑点です。誤差の累積が遅いほど、それらの白いピクセルはより散らばり、より場違いに見えます。最良の解決策は、限られたカラーテーブルを持たない別の画像形式に切り替えることです。たとえば、GIF 形式の画像を PNG に変換します。これにより、色の量子化(減色)の必要がなくなり、ひいては減色された色をディザリングする必要もなくなります。次の解決策は、E-Dither の使用を、整列ディザリングのように誤差を '局所化' する別のディザリング手法に置き換えることです。しかし、現在 IM ではそれを適用するのは簡単なことではありません。より一般的なものが見つかるまでの 1 つの手法については、整列ディザのより良い結果を参照してください。別の画像形式に切り替えたり、別のディザリング手法を使ったりすることが実用的でない場合(そしてしばしばそうです)、その特定の画像について状況を改善しようと試みるしかありません。これに対する最良の修正は、E-Dither の誤差累積を引き起こしている大きな色のグループのすぐ外側に、他の色を確実に持たせることです。しかし、通常の色の量子化はこれを行いません。色のグループを代表する平均色のセットを選ぶ傾向があります。必要なのは、単純な平均色ではなく、大きな色のグループの端を '杭の柵' のように囲む余分な色です。たとえば、ここでは正方形ではなく円を使い、純白の色だけでなく、いくつかの白青の色も追加されるようにしました。これらは、円の端のアンチエイリアスによって、その見た目を滑らかにするために自動的に追加されたものです。 |

  magick -size 100x60 xc:SkyBlue \
          -fill DodgerBlue -draw 'circle 50,70 15,35' \
          -fill RoyalBlue  -draw 'circle 50,70 30,45' -blur 0x5 \
          -fill white -draw 'circle 50,45 40,40' \
          -colors 64  speckle_fixed.gif

[IM Output]
そして、先ほどと同じ領域の拡大図です。 |

  magick speckle_fixed.gif -crop 15x15+85+0 +repage \
          -scale 90x90    speckle_fix_mag.gif

[IM Output]
見てのとおり、追加された色が、青シアンのグラデーションのすぐ外側に余分な色を提供しています。これらの余分な色は実際のグラデーションに使える色が少なくなることを意味しますが、E-Dither が累積誤差が大きくなりすぎる前に、より早く、より頻繁に自身を補正できるようにする他の青白い色を提供します。つまり、E-Dither の斑点を防いだわけではなく、ディザアルゴリズムが使えるより良い色を提供しただけです。画像の拡大された部分をよく見ると、依然として斑点のパターンが見えますが、色は背景色により近く、その数もずっと多くなり、より均等に広がった斑点を生み出しています。もう 1 つの方法は、おそらく IM が生成したものに基づいて独自のカラーテーブルを生成し、誤差の累積を防ぐために適切な色を追加することです。しかし、これは簡単なことではありません。とりわけ 3 次元のカラースペースでは難しいです。この特定の画像例については、'斑点' を防ぐ 1 つの方法は、必要な色よりわずかに少ない色で背景を別個に生成しディザリングし、それから白い箱とその追加色を重ねることです。 |

  magick -size 100x60 xc:SkyBlue \
          -fill DodgerBlue -draw 'circle 50,70 15,35' \
          -fill RoyalBlue  -draw 'circle 50,70 30,45' -blur 0x5 \
          -colors 63 \
          -fill white -draw 'rectangle 40,40 60,55'  speckle_perfect.gif

[IM Output]
これは画像に 'white' の色を追加しますが、誤差補正ディザが使われたときに white が利用できなかったため、背景には斑点効果が一切生じません。その結果は、ちょうど 64 色で、斑点がまったくない画像です。しかし、これは画像と達成しようとしていることに大きく依存するため、斑点問題の一般的な解決策ではありません。
余分な色を追加するよりも一般的な代替策は、最終的にディザされた画像から斑点を取り除こうとすることです。つまり、何らかの方法で画像をクリーンアップするのです。しかし、これ自体がやっかいな問題です。通常のディザリングパターンの一部であるピクセルを取り除きたくはないからです。必要なのは、周囲のすべての色と何らかの形で大きく異なるが、同時に、ある程度の距離をおいて他のすべての類似色からよく孤立している色のピクセルを見つけることです。 もっと良い画像フィルターの解決策をお持ちですか? まとめ 私にとって斑点は非常に厄介な問題で、とりわけ非常に限られたカラーテーブルを使うデスクトップアイコン画像では困ります。私自身、斑点を取り除いたり、垂直方向の縞模様のような他のディザリング効果を修正したりするために、小さな 'アイコン' 画像をしばしば編集します。もっと良い解決策をご存じなら、教えてください。

モノクロのディザビットマップ画像

"[-monochrome](https://imagemagick.org/command-line-options/#monochrome)" オペレータは、ビットマップ画像を生成するための "[-colors](https://imagemagick.org/command-line-options/#colors)" オペレータの特殊な形態です。そのため、'ヒルベルト曲線ディザリング' を実演するだけでなく、色の選択をより詳しく見るのにも理想的なオペレータです。典型的な例を示します。 |

  magick logo.png  -monochrome     monochrome.gif

[IM Output]
このオペレータは、グレースケールの明るさの '強度' または 'レベル' だけに基づいて画像をディザリングします。ただし、グレースケール範囲全体を直接ディザリングするのではなく、最も極端な値をその最大値にしきい値処理します。これは、グラデーション画像をディザリングするよう IM に求めることで確認できます。

  magick -size 15x640 gradient: -rotate 90 \
                   -monochrome     monochrome_gradient.gif

[IM Output]

見てのとおり、グラデーションは "[-monochrome](https://imagemagick.org/command-line-options/#monochrome)" オペレータによって、色のおよそ中央の 50% だけがディザされています。IM の動作のこの興味深い事実を指摘してくれた Ivanova flamingivanova@punkass.com 氏に特別な感謝を捧げます。グレースケール範囲全体を使ってディザリングしたい場合は、(組み込みのパターン画像が提供する)純粋な黒白のカラーマップを使って "[-remap](https://imagemagick.org/command-line-options/#remap)" オペレータを使えます。 |

  magick logo.png  -remap pattern:gray50  mono_remap.gif
  magick -size 15x640 gradient: -rotate 90 \
                   -remap pattern:gray50     mono_remap_gradient.gif

[IM Output]

[IM Output]

"[-remap](https://imagemagick.org/command-line-options/#remap)" を使ってより慎重に色を選択することで、"[-monochrome](https://imagemagick.org/command-line-options/#monochrome)" オペレータが使うのと同じ 'しきい値' 範囲、あるいは好みの任意のしきい値範囲を効果的に生成できます。 |

  magick xc:gray20  xc:white  +append   ctrl_colors.gif
  magick logo.png -colorspace Gray \
          -remap ctrl_colors.gif  -normalize  mono_remap_ctrl.gif
  magick -size 15x640 gradient: -rotate 90 \
          -remap ctrl_colors.gif  -normalize  mono_remap_grad_ctrl.gif

[IM Output]

[IM Output]

"[-monochrome](https://imagemagick.org/command-line-options/#monochrome)" が実際に行うのは、まず与えられた画像をグレースケール画像に変換し、その後、画像をディザリングするしきい値の色を決めるために 2 色の色の量子化を実行することです。これが、次の例の節で探求する内容です。 "[+dither](https://imagemagick.org/command-line-options/#dither)" 設定は、現在 "[-monochrome](https://imagemagick.org/command-line-options/#monochrome)" の結果に影響を与えません。ただし、これは将来変わるかもしれないので、このオペレータを使うときは、スクリプトでそれが無効になっていないことを確認してください。

2 色の量子化

2 つの制御色を自分で選ぶ代わりに、"[-colors](https://imagemagick.org/command-line-options/#colors)" オペレータを使って色の量子化に画像内の最良の 2 色を選ばせることができます。 |

  magick logo.png   -colors 2 -colorspace gray  -normalize \
                                                 colors_monochrome.gif

[IM Output]
しかし、先に画像をグレースケールに変換しなかったため、結果は "[-monochrome](https://imagemagick.org/command-line-options/#monochrome)" を使った場合と同じにはなりません。代わりに、画像は選ばれた 2 つの非グレーの色値の間で直接ディザされました。つまり、2 つのグレースケールの明るさレベルではなく、画像をディザリングするための最良の 2 色が選ばれたのです。その結果、たとえばほぼ同じグレースケール 'レベル' の色だけを使う画像については、より良い結果を生み出します。たとえば、ここでは赤青のグラデーションに対して、"[-colors](https://imagemagick.org/command-line-options/#colors)" と "[-monochrome](https://imagemagick.org/command-line-options/#monochrome)" ビットマップディザリングオペレータを使います。見てのとおり、結果は同じではありません。

  magick -size 20x640 gradient:red-blue -rotate 90    gradient_rb.png
  magick gradient_rb.png   -colors 2 -colorspace gray \
                                -normalize        colors_threshold.gif
  magick gradient_rb.png       -monochrome       mono_threshold.gif

[IM Output] [IM Output] [IM Output]

上記の "[-monochrome](https://imagemagick.org/command-line-options/#monochrome)" オペレータは、青と赤がほぼ同じ強度であるため、ビットマップディザするための差異を一切見つけられませんでした。しかし "[-colors](https://imagemagick.org/command-line-options/#colors)" 量子化手法を使うと、ディザリングする間の許容できる色を見つけるのに何の問題もありませんでした。また、色の中央部分だけがディザされているのもわかります。これは、色の量子化が、選択した 2 つの色の 'クラスタ' の中央の色を選んだためです。選ばれた色の '外側' の色は、ディザリングなしで直接その色にしきい値処理されます。これは、量子化のカラースペースの外側の色はディザされないことを示していますが、この事実を実用的に活用するのは難しいです。 量子化の前に "[-colorspace](https://imagemagick.org/command-line-options/#colorspace)" をグレースケールに設定することで、"[-monochrome](https://imagemagick.org/command-line-options/#monochrome)" オペレータの内部動作を再現できます。 |

  magick logo.png -colorspace gray   -colors 2  -normalize \
                                                 monochrome_equivelent.gif

[IM Output]
そして最後に、ディザリングを無効にすることで、固定された "[-threshold](https://imagemagick.org/command-line-options/#threshold)" 設定を使うよりも自動的な画像内の色の分離を生み出せます。 |

  magick logo.png  -colorspace gray  +dither  -colors 2  -normalize \
           threshold_two_grays.gif

[IM Output]
| "[-monochrome](https://imagemagick.org/command-line-options/#monochrome)" は現在 "[+dither](https://imagemagick.org/command-line-options/#dither)" 設定を無視することを覚えておいてください。そのため、そのオペレータを使って 'スマートしきい値処理' を行うことはできません。
---|---
画像処理の色の量子化段階の "[-colorspace](https://imagemagick.org/command-line-options/#colorspace)" を取り除くと、その画像について可能な(グレースケールの色の分離ではなく)最良の色の分離に基づいて画像をしきい値処理できます。 |

  magick logo.png  +dither  -colors 2  -colorspace gray -normalize \
           threshold_two_color.gif

[IM Output]

定義済みカラーマップを使ったディザ

上で示したように、"[-colors](https://imagemagick.org/command-line-options/#colors)" は画像を表現するための最適な限られた色のセットを選ぼうとします。"[-remap](https://imagemagick.org/command-line-options/#remap)" では、それらの色をディザリングするつもりであれ、単に最も近い隣の色で置き換えるつもりであれ、画像に使いたい最終的な色のセットを IM に与えます。引数は、使いたいすべての色を含む画像として与えます。色数の多い大きな画像をその色の一覧だけに減らしたい場合は、後で "[-remap](https://imagemagick.org/command-line-options/#remap)" で使うために保存する前に、"[-unique-colors](https://imagemagick.org/command-line-options/#unique-colors)" を使えます。 | _"[-remap](https://imagemagick.org/command-line-options/#remap)" オペレータは任意の画像を受け入れますが、この画像に JPEG 画像を使わないでください。さもないと、その 'ロッシー圧縮' が余分な色を生成するため、多くの余分な色が得られてしまいます。

一方で、JPEG を使って余分な色を生成することは、前に見た '斑点' 問題を解決するのに役立つかもしれません!_
---|---
たとえば、ここでは IM ロゴで使う色を、名前付きの X window 色の定義済みマップに制限します。デフォルトは 'Riemersma' ディザですが、IM v6.4.4 以降、"[-dither](https://imagemagick.org/command-line-options/#dither)" は 'FloydSteinberg' のような他のディザ手法を選択できるよう拡張されました。もちろん、依然として "[+dither](https://imagemagick.org/command-line-options/#dither)" オプションを使ってディザリングを無効にできます。

  magick logo.png  -dither None       -remap colortable.gif  remap_logo_no.gif
  magick logo.png  -dither Riemersma  -remap colortable.gif  remap_logo_rm.gif
  magick logo.png  -dither FloydSteinberg \
                                       -remap colortable.gif  remap_logo_fs.gif

[IM Output] [IM Output] [IM Output] [IM Output] [IM Output]

見てのとおり、IM は与えられた色だけを使って画像をそれなりにうまく表現しようとしましたが、その結果は、IM に使う色のセットを選ばせた場合に得られる画像には遠く及びません。とはいえ、この "[colortable.gif](../static/img/images/colortable.gif)" 画像は、画像をディザリングするためにではなく、より原始的な古い X window のカラーディスプレイ向けに漫画のようなカラーアイコンを設計するための色のセットとして設計されたものです(詳細は Anthony's X Window Icon LibraryAIcons Color Selection を参照)。 また、最終的な画像はこのマップが提供する 32 色すべてを使わなかったことにも注意してください。ただし、何らかのディザリングが有効な場合(それぞれ )は、それが無効だった場合()よりも、マップ内のより多くの色が使われます。この最後の例は、良いカラーマップを選ぶことがいかに重要かを示しています。このため、よほど差し迫った理由がない限り、"[-colors](https://imagemagick.org/command-line-options/#colors)" オペレータを使って画像に使われる色の選択を IM に最適化させ、それを自分のニーズに合わせて修正することをお勧めします。もう 1 つの点として、"[-colors](https://imagemagick.org/command-line-options/#colors)" が最良の色のセットを見つけるカラースペースを指定できる一方で、現在のところ色のマッピングやディザリング段階のためのカラースペースは定義できません。私のすべての実験は、色のセットが(誤差補正ディザと最も近い色の置き換えの両方とも)RGB 空間に基づいて適用されることを示しているようです。"[-quantize](https://imagemagick.org/command-line-options/#quantize)" カラースペース設定は、色の選択にのみ使われ、そのマッピングには使われません。では、カラーマップを使うのがそれほど悪い考えなら、なぜそれを使いたいのでしょうか? いくつかの一般的な理由があり、たいていは画像で使われる色の特定のパレットをより細かく制御する必要があるからです。あるユーザーは、Risograph(デジタル印刷システム)で使えるようにカラーマップを分離していました。以下で示していない "[-remap](https://imagemagick.org/command-line-options/#remap)" オペレータを使う別の理由をご存じなら、教えてください。

共通の(または'最良の')カラーマップ

複数の画像を扱うときのもう 1 つの技法は、関係するすべての画像に共通のカラーテーブルを生成することです。基本的に、すべての画像を 1 つの大きな画像に連結し、それから "[-colors](https://imagemagick.org/command-line-options/#colors)" オペレータを使って、すべての画像に共通する良いカラーマップを割り出します。そのカラーマップ画像ができたら、それを使って、たった今生成した定義済みカラーマップで各元画像を再着色できます。あるいは、特殊な "[+remap](https://imagemagick.org/command-line-options/#remap)" オペレータを使うこともできます。これは 255 色のカラーマップに対して同じことを行います。色を数え上げ、良い共通のカラーマップを形成するために色の量子化を実行し、それから必要に応じてそのマップを使うように画像をディザリングします。ただし、"[-remap](https://imagemagick.org/command-line-options/#remap)" と "[+remap](https://imagemagick.org/command-line-options/#remap)" の両方の形式には、GIF アニメーションにとって非常に重要な機能が 1 つあります。それは、すべての画像を、すべての画像が同じ色のパレットを使う 'Palette' という画像 "[-type](https://imagemagick.org/command-line-options/#type)" に変換することです。その理由は、GIF 画像を書き込むとき、最初の画像のカラーパレットがファイル形式の 'グローバルカラーマップ' に使われるからです。それから、各画像が書き込まれるとき、それらの画像が同じ色のセットを使っていることに気づくので、'ローカルカラーマップ' を作成しません。これにより、最終的な GIF ファイル内のすべての画像について、画像 1 つあたり最大 256 × 3、つまり 768 バイトのカラーマップ領域を節約できます。これができるのは "[-remap](https://imagemagick.org/command-line-options/#remap)" オペレータだけです。そのため、GIF、とりわけ GIF アニメーションを扱うときは、覚えておくべき重要な点になります。詳細と例については、GIF アニメーション、グローバルカラーテーブルを参照してください。

Web セーフカラー

WWW が最初に作られたとき、コンピュータのディスプレイは利用できる色の範囲が限られており、Web ブラウザは通常、画像により単純な色のセットを使っていました。そのため、画像を小さくし、ユーザーのブラウザでも問題なく見えるようにするために、この色のセットに画像を再着色するのが一般的でした。詳しくは Web Style Guide, Dithering を参照してください。これを助けるために、IM は "netscape:" と呼ばれる、この 216 色の特殊なテーブルの組み込みカラーマップ画像を提供しました。では、これらの色を使う古い Web ブラウザのディスプレイで、テスト画像がどう見えるか見てみましょう。

  magick logo.png         -remap netscape:  remap_netscape.gif
  magick logo.png +dither -remap netscape:  remap_netscape_nd.gif

[IM Output] [IM Output] [IM Output] [IM Output]

この色のセットは、グラフィックアーティストではなく、ディスプレイとコンピュータのエンジニアによって設計された、数学的に決定されたパレットです。写真のような実際の画像にはそれなりにうまく機能する程度には一般的ですが、ロゴ、背景、グラフのようなコンピュータ生成画像、漫画のような画像など、平らな色の大きな領域を含む画像には非常に不向きです。基本的に、これは色の変化が激しい領域では機能しますが、一定の色の大きな平らな領域では、(一般に)3 色のディザリングが適用されます。たとえば、上記の IM ロゴテスト画像の少し青ずれしたシャツのような部分です。言い換えれば、Web で使う画像やロゴを設計するなら、一般に平らな大きな領域にはこのパレットの色を使うようにし、色の濃淡が変化する領域でのみディザされた色を持たせるようにするでしょう。上記のコマンドを使えば、より原始的なコンピュータディスプレイで画像がどう見えるかをテストし、それらの色を使うように画像を編集して、うまく機能するようにできます。これは、シンボルやナビゲーション画像にとってとりわけ重要です。もちろん今日では、ゲームや Web のユーザーの要求のおかげで、ほとんどのユーザーがあの古い色の制限を持たない現代的なコンピュータディスプレイを持っていると、かなり確信できます。しかし、この "Web セーフパレット" の使用は、画像圧縮のような他の利点があるため、依然として残っています。現代の世界での Web セーフカラーの使用についての議論は、Death of the Web-safe Color Palette?、そしておそらくより重要な、このカラーマップを最初に特定したグラフィックデザイナー Lynda Weinman の見解を参照してください。

カラーマップの生成

任意の画像、または特定の画像のセットについて、良いカラーマップを決定することは非常に重要になりえます。これは、GIF アニメーションに使われる一連の画像を扱っているときにとりわけ重要になります。基本的に、アニメーションの各フレームに別々のカラーテーブルを持たせるのではなく、すべてのフレームに 1 つのカラーテーブルだけが必要になるようにしたいのです。言い換えれば、すべての画像に 1 つの単一のカラーマップが欲しいのです。この場合、選択肢は実質的に 2 つしかありません。どんな画像にもうまく機能するカラーマップを作ろうとするか、あるいは適用する特定の画像のセットに対してカラーマップを最適化しようとするかです。

Web セーフカラーマップ

[IM Output] 最初の方法は、通常、IM の組み込み "netscape:" カラーマップのような、数学的に生成されたカラーマップです。これは 216 色のセットを提供し、GIF 形式の 256 色の制限にうまく収まり、なお画像の透明度を扱ったり、影やテキストオーバーレイのような特別な目的のために余分な色を追加したりする余地が残ります。このカラーマップは、3 つのカラーチャンネルそれぞれに 6 レベルの色を作ることで生成され、6×6×6 色、つまり 216 色を生成しました。獣の数字(訳注: 6 が並ぶことを掛けた洒落)です。219 色しか使われていないため、(GIF 画像については)特定の目的のためにカラーマップにさらに色を追加する余地がまだあります。たとえば、透明な色や、さらなるグレースケールの濃淡などです。古い Macintosh 版の Web セーフマップは、全体的な結果を改善しようと実際にまさにこれを行っていましたが、Macintosh の Web クライアントでのみ使われていました。これは、その単純さと World Wide Web での一般的な使用のおかげで、おそらく一般に使われている最も一般的な '均一な'(または数学的に導出された)カラーマップです。

均一な 332 カラーマップ

一般によく使われるもう 1 つの均一な色マッピングは、"332 RGB カラーマップ" です。この数字は、8 ビットの色インデックス内で各色を表現するのに使われるビット数を指します。つまり、赤に 3 ビット(8 レベル)、緑に 3 ビット、そして青には、私たちの目が青にあまりよく反応しないことを踏まえて、2 ビット(4 色レベル)です。これで 3+3+2 ビット、つまり 8 ビットの色インデックス、すなわち 256 色になります。限られた GIF のカラーテーブルにぴったりです。しかし、GIF の透明色やその他の特別な用途の色のための余地は一切残りません。IM にこのカラーマップを生成させる 1 つの方法を示します… |

  magick -size 16x16 xc: -channel R -fx '(i%8)/7' \
                          -channel G -fx '(j%8)/7' \
                          -channel B -fx '((i>>3&1)|(j>>2&2))/3' \
          -scale 600% colormap_332.png

[IM Output]
| ビットシフトオペレータ '>>' と '<<' は、IM バージョン 6.2.9-2 まで "[-fx](https://imagemagick.org/command-line-options/#fx)" オペレータから欠けていました。
---|---
同じことをするより簡単な方法は、"-ordered-dither threshold,8,8,4" という操作を使って均一な色レベルを使った整列ディザを使うことです(その例の領域を参照)。上記の自作 FX 手法よりはるかに簡単で高速な技法であり、さらにグラデーションをよりよく扱うために他の組み込みディザリングマップを使うこともできます。このマップの唯一の欠点は、実際には 'グレー' の色をまったく提供しないことです。しかし、この欠点はディザリングが使われるときには長所にもなりえます。わずかな色の違いが、グレースケールグラデーションにおける色の境界変化の効果を減らし、ほんの少し滑らかな見た目にするからです。

TrueColor 16bit カラーマップ

上記の '332 カラーマップ' に似た均一なカラーマップが、めったに使われない 16 ビットのビジュアルクラスで X windows によって使われています。この場合、色インデックスに 16 ビットが使われ、赤に 5 ビット、緑に 5 ビット、青に 6 ビットに分割されます。言い換えれば、このカラーマップはむしろ "556 カラーマップ" のようなもので、'threshold' ディザマップを使った均一な色レベルを使った整列ディザで最もよく実現できます。具体的には "-ordered-dither threshold,32,32,64" という操作です。ただし、16 ビットのカラーマップは、カラーマップを使う画像が通常 8 ビットのカラーテーブルを必要とするため、めったに見かけません。そのため、これ以上は触れません。

ガンマ補正された均一なカラーマップ

現時点では、IM はガンマ補正されたカラーマップを直接扱いません。代わりにすべきことは、(IM の Q16 以上のコンパイル時品質バージョンがあると仮定して)ディザリングを行う前に、画像を sRGB や画像が持つ何らかのガンマレベルからリニア RGB モデルに変換することです。これは、リサイズやぼかしなど、他の多くの画像処理操作にも当てはまります。例については、ガンマ補正を使ったリサイズを参照してください。

ポスタライズ、均一なカラーマップによる再着色

このオペレータの本来の目的(引数 '2' を使う)は、画像を基本色だけを使った安価な簡易ポスター印刷手法で生成したかのように、わずか 8 つの基本色を使って再着色することです。そこからこのオペレータの名前が来ています。"[-posterize](https://imagemagick.org/command-line-options/#posterize)" オペレータは、実際には、画像内の各カラーチャンネルについて与えられた色 'レベル' の数に基づいてカラーマップを生成し、誤差補正ディザを使って画像をディザリングする特殊な減色オペレータです。

  magick netscape: -scale 50%  +dither  -posterize 2   posterize_2_ns.gif
  magick netscape: -scale 50%  +dither  -posterize 3   posterize_3_ns.gif
  magick netscape: -scale 50%  +dither  -posterize 6   posterize_6_ns.gif

[IM Output] [IM Output] [IM Output] [IM Output]

見てのとおり、'2' という "[-posterize](https://imagemagick.org/command-line-options/#posterize)" 引数は、カラーチャンネルあたり 2 色だけを提供することを意味し、上記のような 3 チャンネルの RGB 画像については、わずか 8 色のマップを生成します。基本的に、8 色のしきい値セットを使って画像を再着色します。'3' という引数は、中間調の色を含む 27 色のカラーマップに基づいて画像の色をマッピングします。一方、'4' という引数は 64 色のカラーテーブルを生成し、'5' は 125 色のカラーマップを生成します。もちろん、上で述べたとおり、'6' という引数は、組み込みの "netscape:" 画像が提供するのと同じ 216 色のセットを再現します。'0' や '1' という "[-posterize](https://imagemagick.org/command-line-options/#posterize)" 引数は無意味で、最近の IM リリースでは画像を純粋な黒に変換するだけ(論理的ではありますが、まったく役に立ちません)であることに注意してください。その結果、画像は数学的に導出された、つまり '均一な' カラーマップを使って再着色されます。これは、ポスタライズされたグレーレベルの均等な分布を生成するグラデーション画像で、よりはっきりと見えます。

  #magick -size 20x640  gradient: -rotate 90  gradient.png
  magick gradient.png  +dither  -posterize 5   posterize_gradient.gif

[IM Output]

たとえば、IM ロゴ画像をさまざまなレベルでポスタライズしてみましょう…

  magick logo.png  +dither -posterize 2  posterize_logo.gif
  magick logo.png          -posterize 2  posterize_logo_dither.gif
  magick logo.png          -posterize 6  posterize_6_logo.gif

[IM Output] [IM Output] [IM Output] [IM Output]

より良いテストとして、陰影のある "colorwheel" 画像をポスタライズしてみましょう。

  magick colorwheel.png  +dither  -posterize 2   posterize_2_cw.gif
  magick colorwheel.png  +dither  -posterize 3   posterize_3_cw.gif
  magick colorwheel.png  +dither  -posterize 6   posterize_6_cw.gif

[IM Output] [IM Output] [IM Output] [IM Output]

そして、ディザリングを有効にした同じものがこちらです…

[IM Output] [IM Output] [IM Output] [IM Output]

もちろん、次の節で見るビットマップディザの多くも、さまざまな種類のディザスタイルを使って、レベル 2 の整列ディザを生成できます。しかし、より多くのグレーレベルを使えるものはほとんどありません。整列ディザは、IM v6.2.9 以降、均一なカラーマップを使ったディザリングという現在の制限のため、ポスタライズ手法でもあります。しかし、そのディザパターンは、"[-posterize](https://imagemagick.org/command-line-options/#posterize)" が生成する擬似ランダム化されたディザよりも均一で、スタイルの選択肢も豊富です。これらを上記のディザされた "[-posterize](https://imagemagick.org/command-line-options/#posterize)" バージョンと比較してください。

  magick colorwheel.png  -ordered-dither o8x8,2   posterize_2_od.gif
  magick colorwheel.png  -ordered-dither o8x8,3   posterize_3_od.gif
  magick colorwheel.png  -ordered-dither o8x8,6   posterize_6_od.gif

[IM Output] [IM Output] [IM Output] [IM Output]

'threshold' ディザマップ(上記で使った 'o8x8' の代わり)は、"[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)" を効果的にディザリングなしのポスタライズ手法に変えます。最後に、整列ディザでは、各カラーチャンネルごとに異なる色レベル数を指定できます。これは "[-posterize](https://imagemagick.org/command-line-options/#posterize)" オペレータが現在許可していないことです。


しきい値ディザリングの手法

しきい値画像

画像を白黒のビットマップ(色)画像に変換する最も単純な手法は、"[-threshold](https://imagemagick.org/command-line-options/#threshold)" を使うことです。これは実際には、単に区切り値を提供する単純な数学的オペレータです。その値以下のものはすべて黒になり、それより大きいものはすべて白になります。

  magick logo.png     -threshold   -1   threshold_0.gif
  magick logo.png     -threshold  25%   threshold_25.gif
  magick logo.png     -threshold  50%   threshold_50.gif
  magick logo.png     -threshold  75%   threshold_75.gif
  magick logo.png     -threshold 100%   threshold_100.gif

[IM Output] [IM Output] [IM Output] [IM Output] [IM Output]

見てのとおり、'-1' という値はすべての色を白に変換し、'100%' はすべての色を黒に変換します。'50%' はもちろん最もよく使われる値です。 '0' という値は特殊なケースで、純粋な黒でないすべての色を白にします。もちろん、画像に純粋な黒の色がなければ、真っ白な画像になるだけです! |

  magick logo.png  -threshold   0    threshold_black.gif

[IM Output]
純粋な白でないすべての色を黒に変換したい場合は、使うべき正しいしきい値(IM の現在の 'MaxRGB' より 1 少ない値で、これはお使いの IM の特定のコンパイル時の品質、つまり 'Q'設定に依存する値です)を割り出そうとするのではなく、ネガ化した画像をしきい値処理することをお勧めします。 |

  magick logo.png  -negate -threshold 0 -negate threshold_white.gif

[IM Output]
"[-threshold](https://imagemagick.org/command-line-options/#threshold)" オペレータは、しきい値レベルによって色の差を最大化する究極の 'コントラスト' オペレータとして分類できます。ただし、これはグレースケールオペレータであり、"[-channel](https://imagemagick.org/command-line-options/#channel)" 設定を使って、オペレータがどのカラーチャンネルに適用されるかを調整できます。たとえば、画像の個々のチャンネルそれぞれをしきい値処理して、ディザリングなしのレベル 2 の "[-posterize](https://imagemagick.org/command-line-options/#posterize)" 操作と同じ効果を生み出せます。 |

  magick logo.png  -channel R -threshold 50% \
                     -channel G -threshold 50% \
                     -channel B -threshold 50%   threshold_posterize.gif

[IM Output]
| "[-threshold](https://imagemagick.org/command-line-options/#threshold)" は、画像内のあらゆる透明度を、アルファチャンネルではなくマット(matte)チャンネルとして扱う(IM 内部で格納されているのとちょうど同じように)ことに注意してください。そのため、このオペレータをアルファチャンネルに適用する予定なら注意が必要です。詳細はマットチャンネルを参照してください。
---|---
より自動的なしきい値処理の技法としては、前に示した2 色の量子化の技法を使えます。 たとえば、これは画像内で見つかった最良の 2 色に基づいて画像をしきい値処理します。これらの色は必ずしもグレースケールや反対色である必要はなく、画像全体を最もよく表現する 2 つの色というだけです。それから、2 つの色は("[-normalize](https://imagemagick.org/command-line-options/#normalize)" を使って)純粋な黒と白にマッピングされます。 |

  magick logo.png  +dither  -colors 2  -colorspace gray -normalize \
             threshold_two_color.gif

[IM Output]

しきい値処理によるランダムディザ

"[-random-threshold](https://imagemagick.org/command-line-options/#random-threshold)" オペレータは、ビットマップ画像変換器の特殊な形態です。この場合、非常に単純な "ランダムディザ" を使って、特定のピクセルが白いピクセルになるか黒いピクセルになるかを決めます。"[-threshold](https://imagemagick.org/command-line-options/#threshold)" や "[-monochrome](https://imagemagick.org/command-line-options/#monochrome)" オペレータ、あるいは前の節のバリエーションとは異なり、選択されたチャンネル("[-channels](https://imagemagick.org/command-line-options/#channels)" で設定)は単一のグレースケールチャンネルに統合されて 1 つの単位としてディザされることはありません。代わりに、"[-random-threshold](https://imagemagick.org/command-line-options/#random-threshold)" は選択された各チャンネルを互いに完全に独立して処理します。 もちろん、このオペレータを直接使うと、ランダムディザを使った画像の 2 レベルのポスタライズになります。 |

  magick logo.png  -random-threshold  0x100%  random_posterize.gif

[IM Output]
グレースケールに変換すると、ディザされる前に画像内のすべてのチャンネルが均等化されます。しかし、各チャンネルは互いに独立してランダムな方法でディザされるため、結果は期待するようなビットマップ画像にはなりません。代わりに、とりわけ中間調の色について、色付きピクセルの飛び散りが得られます。 |

  magick logo.png  -colorspace Gray -random-threshold  0x100% \
                                                   random_greyscale.gif

[IM Output]
適切なランダムディザのビットマップ画像を生成する正しい方法を示します。 |

  magick logo.png  -colorspace Gray -channel B \
          -random-threshold 0x100%    -separate   random_monochome.gif

[IM Output]
基本的に行ったのは、グレースケール化した画像の 1 つのチャンネルだけをディザし、それから "[-separate](https://imagemagick.org/command-line-options/#separate)" チャンネルオペレータを使って、そのチャンネルを最終的なビットマップ画像として抽出することです。トリッキーですが効果的です。 このオペレータの特別な機能として、特殊な "[-channels](https://imagemagick.org/command-line-options/#channels)" オプションの 'All' が使われた場合、IM はビットマップ画像が生成されることを保証します。 |

  magick logo.png  -channel All -random-threshold 0x100% random_all.gif

[IM Output]
ただし、この方法ではアルファチャンネルが無視され失われることに注意してください。そのため、通常は推奨されません。私自身、この古い機能はソースコードから偶然発見しただけです。さて、カラー画像から正しくビットマップを生成するオペレータの使い方がわかったところで、引数がディザリングの範囲にどう影響するかを見てみましょう。これは、このディザが生み出すピクセルの 'かたまり' もはっきりと示します。

  #magick -size 20x640  gradient: -rotate 90  gradient.png
  magick gradient.png  -channel All \
                        -random-threshold 0x100%  random_grad_0x100.gif
  magick gradient.png  -channel All \
                        -random-threshold 10x90%  random_grad_10x90.gif
  magick gradient.png  -channel All \
                        -random-threshold 25x75%  random_grad_25x75.gif
  magick gradient.png  -channel All \
                        -random-threshold 50x50%  random_grad_50x50.gif

[IM Output] [IM Output] [IM Output] [IM Output]

'0x100%' という "[-random-threshold](https://imagemagick.org/command-line-options/#random-threshold)" 設定は、画像の純粋な 'ランダムディザ' を生成します。2 つの境界を同じ値に(あるいは互いに交差させて)設定すると、純粋な "[-threshold](https://imagemagick.org/command-line-options/#threshold)" 画像を生成するだけになります。それ以外の境界のセット(通常はパーセンテージで指定)を使うと、与えられた範囲外ではビットマップにしきい値処理し、与えられた範囲内の値についてはランダムディザのパターンを生成します。 "[-monochrome](https://imagemagick.org/command-line-options/#monochrome)" オペレータを使って得られるのとちょうど同じように、わずかに狭い範囲を使うことで最良の結果が得られます。ほとんどの場合、'30x80%' あたりの値がおそらく最良の結果になります。 |

  magick logo.png  -channel All -random-threshold 30x80%  random_30x80.gif

[IM Output]
もちろん、結果は依然としてあまり良くありません。しかし、これは得られる中で最も単純で最悪の形のディザリングです。実際に起きているのは、ランダム化されたディザパターンが、滑らかなディザパターンではなく、ピクセルの 'かたまり' を生み出す傾向があることです。これは、乱数生成器の高周波 'ノイズ' によるものです。しかし、非常に高い解像度では、十分にランダムであれば、ランダムディザは極めて良い結果を生み出すことが示されています。IM は暗号レベルのランダム性を使うため、おそらく非常にランダムでしょう。ただし、画像がこのように役立つほど十分に高い解像度で使われることはめったにありません。このディザに対して提案されている 1 つの '修正' は、ランダムな 'ブルーノイズ' 生成器(音響制作で使われる低周波 'ピンクノイズ' フィルターとは対照的な、高周波フィルター)を使うことです。これはピクセルのかたまりを取り除くはずですが、デジタルで実装するのは非常に難しいです。'ブルーノイズランダムディザ' の既知の実装は見つかっておらず、これから作られることもなさそうです。


整列ディザ

ランダムディザがピクセルのランダムなかたまりを生み出し、さまざまな誤差補正ディザが本質的にランダムなドットのパターンを生み出すのに対し、整列ディザは基本的にその正反対です。これは、できる限り数学的に決定論的になるように設計されています。あまりにも決定論的なので、画像をディザリングするのに使うべきパターンを実際に指定する必要があります。"[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)" オペレータは、画像内の選択された各 "[-channels](https://imagemagick.org/command-line-options/#channels)" を、与えられた定義済みパターンでディザリングします。引数が使うパターン(しきい値マップとして知られる)を定義します。これらのしきい値マップは、基本的に 3 つのスタイルに分かれます。ピクセルが 'かたまり' やタイリングのアーティファクトを避けるために、互いにできるだけ離れて配置される拡散ピクセルディザ。あるいは、機械的に印刷しやすいように、ピクセルを密なドットにまとめる、デジタルハーフトーンとして知られる技法です。また、これから見るいくつかの特殊な芸術的しきい値マップもあり、さらには独自のディザリングパターンやしきい値マップを設計することもあります。いずれの場合も、しきい値マップ内でオンまたはオフになるピクセルの数は、ビットマップにディザリングされる画像(または個々のカラーチャンネル)のグレーレベルの強度に依存します。マップは一貫した方法でピクセルのしきい値レベルを追加するので、あるピクセルが特定の 'しきい値' でいったんオンになると、それより明るいグレーの色についてはオンのままになります。この一貫性は非常に重要です。さもないと、ディザパターンの変化の境界に沿ってアーティファクトが生み出されます。これについて重要な点は、画像内の各ピクセルの結果が、画像内の他のどのピクセルとも独立して、純粋に数学的に決定されることです。そのため、元の画像へのどんな小さな変化も、上で見たように誤差補正ディザが抱える問題とは違って、他の領域の画像にまったく影響を与えません。この点は、ビデオ画像や最適化されたアニメーションの一貫したディザリングにとって不可欠です。

拡散ピクセルディザリング

整列ディザの本来の目的、そして整列ディザを使うときにほとんどのグラフィックプログラマが得られると期待するものは、より正確には "拡散ピクセル整列ディザ" と呼ばれることがあります。これが意味するのは、しきい値の強度が増すにつれて、ピクセルが互いにできるだけ離れて均等に分布するように、タイル状のマップにピクセルが追加されることです。これは、非常に一貫したパターンを生み出し、ほとんどの現代的なディスプレイでは非常に滑らかでほとんど見えないように見えます。そうしたパターンは、2 のべき乗のタイリングサイズ、つまり 2、4、8 のタイルサイズについて割り出されています。ただし、IM は 3×3 のしきい値マップタイルについても、それなりのしきい値パターンを提供しています。IM が現在提供する組み込みの整列ディザの現在のセットを示します。引数が整列ディザのタイルサイズを反映していることを覚えておいてください。

  magick logo.png    -ordered-dither o2x2    logo_o2x2.gif
  magick logo.png    -ordered-dither o3x3    logo_o3x3.gif
  magick logo.png    -ordered-dither o4x4    logo_o4x4.gif
  magick logo.png    -ordered-dither o8x8    logo_o8x8.gif

[IM Output] [IM Output] [IM Output] [IM Output]

より大きなタイルサイズが、より多くの '色レベル' をシミュレートできる一方で、特定のレベルでより目立つ欠陥やピクセルの矩形配列も生成することに注目してください。 | _'o8x8' 整列ディザは長い間 IM のコアコードの一部でしたが、使われていませんでした。これは、IM Examples がこのオペレータの使用を詳述し始めた IM v6.2.9 で、"[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)" オペレータのオプションとして追加されただけでした。

このとき、"[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)" オペレータのさらなる拡張を可能にするために、マップにより決定的な名前が与えられました。ただし、後方互換性のある古い 'タイルサイズ' の名前は、新しい名前のエイリアスとして保持されました。

また、'o3x3' と 'o4x4' を生成していた 'マップ' は、より良い '拡散ピクセル' ディザパターンを生成するように完全に改訂されました。これより前、これらのマップははっきりとしたピクセルの 'かたまり' を生み出していました。

修正される前の古いパターンの例や、IM v6.3.0 でのアップグレードの公式リリースに向けた開発中に行われた他の変更については、整列ディザのアップグレードに関する注記ページを参照してください。_
---|---
もちろん、画像内のすべてのチャンネルの適切なビットマップを生成するには、まず画像をグレースケールに変換する必要があります。しかし、このプロセスはランダムではないため、"[-random-threshold](https://imagemagick.org/command-line-options/#random-threshold)" オペレータで必要だったように画像を後処理する必要はなく、物事が大幅に簡単になります。

  magick logo.png -colorspace Gray  -ordered-dither o2x2  logo_bw_o2x2.gif
  magick logo.png -colorspace Gray  -ordered-dither o3x3  logo_bw_o3x3.gif
  magick logo.png -colorspace Gray  -ordered-dither o4x4  logo_bw_o4x4.gif
  magick logo.png -colorspace Gray  -ordered-dither o8x8  logo_bw_o8x8.gif

[IM Output] [IM Output] [IM Output] [IM Output]

参考までに、それぞれの "[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)" '拡散ピクセル' パターンをグレースケールグラデーションに適用したものを示します。これで、それらがどう見えるかをはっきりと確認できます。

  # しきい値非ディザ / 最小限のチェッカーボードディザ
  magick gradient.png   -ordered-dither threshold  od_threshold.gif
  magick gradient.png   -ordered-dither checks     od_checks.gif
  # 拡散ピクセルディザ
  magick gradient.png   -ordered-dither o2x2       od_o2x2.gif
  magick gradient.png   -ordered-dither o3x3       od_o3x3.gif
  magick gradient.png   -ordered-dither o4x4       od_o4x4.gif
  magick gradient.png   -ordered-dither o8x8       od_o8x8.gif

[IM Output] [IM Output]


[IM Output] [IM Output] [IM Output] [IM Output]

特定の整列ディザが生み出す実効的なすなわち擬似レベルのパターンの数は、通常(常にではありませんが)、パターン内のピクセル数に 1 を加えた数に等しくなります。そのため、'o3x3' 整列ディザは、結果の画像にチャンネルあたり 3×3+1、つまり 10 の実効的なグレーレベル(黒、白、および 8 つの人工的なグレーパターン)を生み出します。上記には、2 つの特殊な最小限のディザしきい値マップも示されています。

  1. 余分なグレーレベルを一切生み出さない、ストレートな '50% しきい値' 非ディザ。
  2. 結果のグラデーションに 1 つの余分な '擬似レベル' を追加するために単一のパターンだけを挿入する、'checks' すなわちチェッカーボードのディザパターン。

デジタルハーフトーンディザ

"[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)" は、IM v6.2.8-6 で、デジタルハーフトーンのディザパターンのセットで拡張されました(Glenn Randers-Pehrson 氏に感謝)。これらはすべて、単純な 45 度のドットパターンを生成するように設定されていました。IM v6.3.0 では、これがさらに、角度のない大きめのハーフトーンの同様のセットで拡張されました。 IM v6.3.0 のリリースより前、ハーフトーンスクリーンは '{number}x1' という形式の引数を使って選択されていました。整列ディザの再開発により、この制限が取り除かれ、より良い名前が選ばれ、余分なハーフトーンスクリーン(直交形式)が追加されました(下記の引数の例を参照)。
デジタルハーフトーンは、紙、厚紙、あるいは金属のような媒体にインクの丸いドットを機械的に堆積させることを扱うように設計された、厳密な意味での真のハーフトーンスクリーンではないことに注意してください。そうしたドットは、印刷プロセス中に重なり合ったり、にじんだりすることがあるため、何らかの非線形のレベル調整が必要になります。これは、純粋にデジタルなハーフトーン効果を生成するには不要です。プロセスの詳細については、ドキュメント Dithering and Halftoning (PDF) を参照してください。とはいえ、整列ディザのデジタルハーフトーンパターンは、新聞や安価に印刷された雑誌で見られるのと同じ基本的な効果を提供します。
  # ハーフトーンスクリーン (45 度の角度)
  magick logo.png   -ordered-dither h4x4a    logo_h4x4a.gif
  magick logo.png   -ordered-dither h6x6a    logo_h6x6a.gif
  magick logo.png   -ordered-dither h8x8a    logo_h8x8a.gif
  # ハーフトーンスクリーン (直交)
  magick logo.png   -ordered-dither h4x4o    logo_h4x4o.gif
  magick logo.png   -ordered-dither h6x6o    logo_h6x6o.gif
  magick logo.png   -ordered-dither h8x8o    logo_h8x8o.gif

[IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]

ここでも、画像の真のビットマップディザを生成するには "[-colorspace](https://imagemagick.org/command-line-options/#colorspace)" オペレータを使います。

  # ハーフトーンスクリーン (45 度の角度)
  magick logo.png -colorspace Gray  -ordered-dither h4x4a logo_bw_h4x4a.gif
  magick logo.png -colorspace Gray  -ordered-dither h6x6a logo_bw_h6x6a.gif
  magick logo.png -colorspace Gray  -ordered-dither h8x8a logo_bw_h8x8a.gif
  # ハーフトーンスクリーン (直交)
  magick logo.png -colorspace Gray  -ordered-dither h4x4o logo_bw_h4x4o.gif
  magick logo.png -colorspace Gray  -ordered-dither h6x6o logo_bw_h6x6o.gif
  magick logo.png -colorspace Gray  -ordered-dither h8x8o logo_bw_h8x8o.gif

[IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]

そして最後に、ハーフトーンのディザパターンと、グレーレベルが変化するにつれてディザパターン内のピクセルのかたまりが互いに成長して結びつく様子をはっきりと示す、もう 1 つのグラデーション参照画像です。

  # ハーフトーンスクリーン (45 度の角度)
  magick gradient.png   -ordered-dither h4x4a      od_h4x4a.gif
  magick gradient.png   -ordered-dither h6x6a      od_h6x6a.gif
  magick gradient.png   -ordered-dither h8x8a      od_h8x8a.gif
  # ハーフトーンスクリーン (直交)
  magick gradient.png   -ordered-dither h4x4o      od_h4x4o.gif
  magick gradient.png   -ordered-dither h6x6o      od_h6x6o.gif
  magick gradient.png   -ordered-dither h8x8o      od_h8x8o.gif
  magick gradient.png   -ordered-dither h16x16o    od_h16x16o.gif
  # 円のハーフトーン (黒と白)
  magick gradient.png   -ordered-dither c7x7b      od_c7x7b.gif
  magick gradient.png   -ordered-dither c7x7w      od_c7x7w.gif

[IM Output] [IM Output] [IM Output]


[IM Output] [IM Output] [IM Output] [IM Output]


[IM Output] [IM Output]

ImageMagick バージョン 6.2.9 まで、上記のしきい値整列ディザマップが IM で可能なすべてでした。これは今や変わり、ユーザーが独自のパターンを追加したり、それを IM コミュニティに提供したりできるようになりました。'円' のハーフトーンしきい値は、IM v6.6.5-6 で Glenn Randers-Pehrson 氏によって追加されました。

オフセットハーフトーンディザ

上記のハーフトーンディザの唯一の問題は、まったく同じしきい値マップ(タイル)がすべてのカラーチャンネルに同じように適用されることです。つまり、同じ原色のセットが、同じ '中心' を持つドットに配置されます。'オフセット印刷' として知られるものを得るには、色が小さなスケールの 'ロゼットパターン' を形成するように、しきい値パターンを特定のパターンで回転させます。これにより、そうしなければ生じてしまうもっと見苦しい干渉(モアレ)パターンが破壊されます。この図は基本的にプロセスを説明しており、Wikipedia のページ Halftone で非常に詳しく説明されています。

[IM Output]

ただし、回転したスクリーンはあまりうまくタイリングしないことに注意してください。そのため、最良の考えは、タイル状のしきい値パターンを使うのではなく、実際に回転したパターンを直接生成することです。小さく回転した 2x2 ピクセルのチェッカーボードパターン(使える中でほぼ最小の 'スクリーン')を使って、画像にオフセットハーフトーン印刷の見た目を与える 1 つの方法を示します。 |

  magick colorwheel.png  -set option:distort:viewport '%wx%h+0+0' \
          -colorspace CMYK -separate null: \
          \( -size 2x2 xc: \( +clone -negate \) \
                +append \( +clone -negate \) -append \) \
          -virtual-pixel tile -filter gaussian \
          \( +clone -distort SRT 60 \) +swap \
          \( +clone -distort SRT 30 \) +swap \
          \( +clone -distort SRT 45 \) +swap \
          \( +clone -distort SRT 0 \)  +swap +delete \
          -compose Overlay -layers composite \
          -set colorspace CMYK -combine -colorspace RGB \
          offset_colorwheel.png

[IM Output]
4 つの回転した 'スクリーン' は画像全体に適用され、実際に 4 つの異なるカラーチャンネルをスクリーン処理された画像から抽出するのは、CMYK カラースペースでの "-combine" ステップだけであることに注意してください。また、最後の 'black' チャンネルの 'no-op'(無操作)ディストートは重要です。それは、そのスクリーン自体は回転していないにもかかわらず、入力のチェッカーパターンを、他のチャンネルの回転中にそれらに使われたガウシアンフィルターに従ってぼかすからです。そしてここでは、回転したタイルを生成するために使った SRT ディストートのスケーリング機能を使って、わずかに大きくよりぼやけた 'スクリーンパターン' を作成しています。

  magick parrots_med.png  -set option:distort:viewport '%wx%h+0+0' \
          -colorspace CMYK -separate null: \
          \( -size 2x2 xc: \( +clone -negate \) \
                +append \( +clone -negate \) -append \) \
          -virtual-pixel tile -filter gaussian \
          \( +clone -distort SRT 2,60 \) +swap \
          \( +clone -distort SRT 2,30 \) +swap \
          \( +clone -distort SRT 2,45 \) +swap \
          \( +clone -distort SRT 2,0  -blur 0x0.7 \) +swap +delete \
          -compose Overlay -layers composite \
          -set colorspace CMYK -combine -colorspace RGB \
          offset_parrots.png

[IM Output]

パターンが、とりわけ他のすべての元になっている black スクリーンが、非常に '正方形のよう' なままであることに注意してください。将来の可能性: 上記の 2 ピクセルのチェッカーボードを、ピクセルレベルのチェッカーボードパターンである "pattern:gray50" に置き換える。ガウシアンフィルターのオプションを使って、スケーリングされたパターンのぼかし具合を調整できます。あるいは、パターンをぼかしてスケーリングし、それをしきい値処理して、より丸いドットを作ることもできます。これを前のように回転させて 4 色のスクリーンを作成できます。また、上記で使ったチェッカーボードパターンよりも、六角形のドットのパターンを使ったより大きなスクリーンが使えれば、なお良いでしょう。
これは真のオフセット印刷のように実際に色のドットを生成しているのではなく、単に色のスクリーンを元の画像に乗算することでそれを模倣しているにすぎないことに注意するのが重要です。緑の背景に対する赤いオウムの端に沿った鋭い色の変化を見れば、これが事実だとわかります。純色のドットだけを使った真のオフセット印刷では、ドットの途中で色が変化することはありません。変化すべきは純色のドットのサイズであり、それはソース画像のドットが表現するその領域の色の平均に依存します。各カラーチャンネルで適切なサイズの丸いドットだけを含む真のオフセット印刷画像を実際に生成するには、はるかに多くの作業が必要です。各カラーチャンネルの各ドットの平均色を決定し、そこから適切なサイズの色付きドット(アンチエイリアスされた円)を生成する必要があります。誰か挑戦してみたい人はいますか? 上記は、Photoshop がどう '模倣' しているか、そして ImageMagick で同じ効果をどう達成できるかを見た IM フォーラムの議論 CMYK Halftone Effect から来ています。この議論は、適切なサイズの実際のドットを使って真のハーフトーンスクリーンを生成することをより詳しく見た B/W Halftone Dither にも関連しています。ただし、その議論はオフセット(回転)スクリーンを使う次のステップまでは進みませんでした。そうしたスクリーンは、おそらくドットを生成するために画像を回転させ、それから特定のカラーチャンネルについてそのドットパターンを再び回転させて戻す必要があるでしょう。

XML しきい値マップ

IM バージョン 6.3.0 から、(以前示した)IM のソースコードに組み込まれた固定のマップのセットを使うのではなく、マップはプログラム自体の外部にある XML データファイルのセットから読み込まれるようになりました。この変更の一環として、"[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)" オペレータが使える 'しきい値マップ' の一覧を表示できるようになりました。

  magick identify -list threshold

[IM Output]

上記の一覧は、利用可能なしきい値マップだけでなく、後方互換性や別名のために提供されているエイリアス、そして私自身の個人的な "thresholds.xml" XML データファイル(私のホームの ".magick" サブディレクトリに保存)で定義されているものも示しています。"[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)" がマップを探すとき、上記の一覧で最初に見つかったマップが使われます。そのため、システム定義のしきい値パターンを上書きすることはできません。システムファイル "thresholds.xml"(そのパスは上記の "[-list](https://imagemagick.org/command-line-options/#list)" オプションで与えられます)には、XML ファイルの形式の完全な要約が含まれています。これは(IM によるエラーチェック付きで)十分に単純な形式なので、ユーザーが独自の整列ディザしきい値マップを定義・作成できます。たとえば、私が個人的な "threshold.xml" ファイルで定義した 'diag5x5' しきい値マップのコピーを示します。

[IM Output]

見ると、しきい値レベルが増すにつれて太くなる単一の対角線の単純な 5x5 マップを作成しています。マップ内のレベル番号は 0 から 5 までで、除数より 1 少なく、これは色のグラデーションをいくつの 'グレー' に分割する必要があるかを宣言します。この個人的なしきい値マップを使ってディザされたグラデーションを示します。

  magick gradient.png   -ordered-dither diag      od_diag.gif

[IM Output]

そして、私がそのために設計した目的である、単純な影付き画像のアルファチャンネルをそのしきい値でディザリングする例を示します。

  magick -size 70x60 xc:none -font Candice -pointsize 50 \
          -fill black -annotate +10+45 'A' -channel RGBA  -blur 0x5 \
          -fill white -stroke black -draw "text 5,40 'A'"   shadow.png

  magick shadow.png  -channel A  -ordered-dither diag   shadow_diag.gif

[IM Output] [IM Output]

なかなかかっこいいでしょう! アルファチャンネルのディザリングについては後でさらに説明します。まず、拡張された "[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)" オペレータの着色機能の使い方も示す必要があります。

均一な色レベルによる整列ディザ

IM v6.3.0 のリリースにより、"[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)" が使うしきい値マップが外部ファイルから読み込まれるように変更されただけでなく、内部の操作も、数学的に定義された 'ポスタライズされた' カラーマップを使えるように強化されました。これは、'誤差補正ディザリング' で達成できるよりも決定論的な画像のディザリングを生成できることを意味します。これは、フレーム間の色の違いから問題が生じないため、アニメーションを含む減色にとってとりわけ重要です。ポスタライズのレベルは、使うしきい値マップの名前に追加された、カンマ区切りの数字のリストを使って "[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)" の引数に渡されます。数字が提供されない場合、オペレータは通常の 2 色(つまりポスタライズレベル 1)のカラーマップにフォールバックします。たとえば、'checks,6' という引数は、古典的な Web セーフカラーマップ(ポスタライズレベル 6)のカラーマップ(組み込みの "netscape:" カラーマップ画像でも定義されている)を使います。しかし、最小限のディザマップ 'checks' が使われるため、6 つの色レベルそれぞれの間に 1 つの余分なディザリングのレベルが追加され、画像の各チャンネルに 11 の擬似レベルの色を作り出します。言い換えれば、チャンネルあたり 6 レベルの色しか使われていない(6^3、つまり 216 色を生成する)にもかかわらず、レベル間の単一のディザパターンが、ディザを実効的に 11 レベル(実効的に 11^3、つまり 1331 色を生成する)に増やします。たとえば、6 つのグレーレベルとさまざまなしきい値マップを使ってディザされたグレースケールグラデーションを示します。最初のマップ 'threshold' は特殊な非ディザの整列ディザしきい値マップで、使われた色だけを示しています。

  magick gradient.png   -ordered-dither threshold,6  od_threshold_6.gif
  magick gradient.png   -ordered-dither checks,6     od_checks_6.gif
  magick gradient.png   -ordered-dither o2x2,6       od_o2x2_6.gif
  magick gradient.png   -ordered-dither o4x4,6       od_o4x4_6.gif
  magick gradient.png   -ordered-dither o8x8,6       od_o8x8_6.gif

[IM Output] [IM Output] [IM Output] [IM Output] [IM Output]

見てのとおり、6 色しか使われていないにもかかわらず、整列ディザリングを使うとグラデーションを定義するのに使われる実効的な色数が増え、実際にいかに少ない色しか使われていないかを見分けるのが難しいほどです! すべてのチャンネルについてポスタライズのレベル数を定義できるだけでなく、"[-posterize](https://imagemagick.org/command-line-options/#posterize)" 誤差補正ディザオプションとは違って、各チャンネルのレベルを指定できます。数字は "[-channels](https://imagemagick.org/command-line-options/#channels)" 設定に従ってチャンネルに割り当てられます。たとえば、ここでは特殊な 332 カラーマップ(赤と緑に 8 レベル、青に 4 レベル)を使ってグラデーションをディザしました。これは合計 256 色を定義します。

  magick gradient.png   -ordered-dither o8x8,8,8,4   od_o8x8_884.gif

[IM Output]

チャンネルごとの色レベル数が異なるため、上記の画像は純粋なグレーの色だけを含むのではなく、互いに打ち消し合って余分なレベルのグレーを生み出す、いくらかの青みがかったピクセルと黄みがかったピクセルを含んでいます。では、整列ディザバージョンを、ポスタライズレベル 2 と 6、そして "332 カラーマップ"(赤と緑に 8 レベル、青に 4 レベル)を使った誤差補正ディザバージョンと比較してみましょう。

  magick logo.png  -ordered-dither o8x8        logo_o8x8_2.gif
  magick logo.png  -posterize 2                logo_posterize_2.gif
  magick logo.png  -ordered-dither o8x8,6      logo_o8x8_6.gif
  magick logo.png  -posterize 6                logo_posterize_6.gif
  magick logo.png  -ordered-dither o8x8,8,8,4  logo_o8x8_332.gif
  magick logo.png  -remap colormap_332.png     logo_remap_332.gif

[IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]

上記の各ペアの最初の画像は数学的に整列ディザされており、2 番目は擬似ランダムに '誤差補正' ディザされています。最後のペアは特殊な '332 カラーマップ'(カラーマップの生成を参照)を使っており、これは 256 色の制限を持つ一般的な画像にとっておそらく最良のポスタライズカラーマップとみなされています。チャンネルのレベルの奇妙な違いが、この漫画のような画像にわずかに良い色の陰影を生み出しています。"[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)" オペレータが各カラーチャンネルに別々のレベルを指定する機能を含んだのは、この '332 カラーマップ' の生成を可能にするためでした。

整列ディザのより良い結果

たった今生成したレベル 6 の整列ディザをより詳しく見てみましょう。

  magick logo.png -ordered-dither o8x8,6 -format %k info:

[IM Text]

見てのとおり、この画像については GIF のカラーテーブル(256 の制限)を埋めることにすら遠く及びませんでした。基本的に、この画像はほとんどが青い色で構成されているため、レベル 6 の均一なカラーマップから、赤や緑の色合いはごくわずかしか使われませんでした。しかし、ポスタライズのレベル数を増やすことで、GIF のカラーテーブルをよりよく埋め、より良い整列ディザ画像を生成できます。

  magick logo.png -ordered-dither o8x8,13 -format %k info:

[IM Text]

これは、GIF のカラーテーブルの制限よりわずかに小さいだけの十分な数の色を生成します。色数が増えることで、結果は単純な標準の均一なカラーマップの結果よりもずっと良く見えます。 |

  magick logo.png -ordered-dither o8x8,13    logo_o8x8_13.gif

[IM Output]
見てのとおり、高い 'レベル' 値を使うと、"[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)" は、色の量子化と誤差補正ディザによって生成される特定の色選択に匹敵する、色の量子化された画像を生成できます。これらの画像について重要な点は、それらが高品質であることではありません。結局のところ、完全な色の量子化の方が、画像により良いカラーマップをより簡単に生成できます。重要なのは、画像内の低レベルのディザパターンが、起こりうるどんな小さな変化にもかかわらず固定されていることです。整列ディザ画像では、領域の変化だけが変更されます。つまり、GIF アニメーションのフレーム最適化に問題を引き起こす、変化への E-Dither の敏感さを持たないのです(参照: 最適化の問題)。もちろん、アニメーションについては、実際に何色使われているかを確認する前に、すべての画像を "[-append](https://imagemagick.org/command-line-options/#append)" で連結する必要があります。そして、色の削減とディザリングをすでに実行済みであっても、すべての画像について 'グローバルな共通カラーマップ' を生成するよう IM に強制するために、"[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)" を使った後に特殊な "[+remap](https://imagemagick.org/command-line-options/#remap)" オプションを使う必要があります。色レベル数を決定するこの方法は、決定するのが簡単ではありませんが、機能します。とりわけ GIF アニメーションについて、IM が最良のレベルを自動的に決定する方法を考え出したいと思っています。


自作ディザパターンとしきい値マップ

前に、新しい "[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)" オペレータがユーザー定義のディザリングパターンを受け入れられることを示しました。ここでは、独自のディザパターンを作成する方法を示します。具体的には、水平線からなる影を生成するのに役立つと私が気づいた特殊なパターンです。

マルチイメージのディザパターン

最初にすべきことは、作りたいパターンを定義する画像のセットを作成することです。パターンは、最初の画像として適切なサイズの無地の黒い画像(すべてのピクセルがオフ)で始まり、もう一端には無地の白い画像(すべてのピクセルがオン)を置くべきです。次の画像は、中央の 50% グレーのパターンで、達成しようとしているディザリングの基本的なスタイルを定義します。たとえば、これが私の最初の自作ディザパターンです。これをマルチイメージの GIF ファイル(GIF アニメーションではない)に保存します…

  magick -size 2x2 xc:black \
          \( +clone -draw 'fill white line 0,0 1,0' \) \
          xc:white     dpat_hlines2x2.gif
  montage dpat_hlines2x2.gif    -tile x1 -background none -frame 2 \
          -filter box  -geometry 32x32+5+0    dpat_hlines2x2_imgs.gif

[IM Output]

これは得られる中でほぼ最も単純なディザパターン画像のセットで、'checks' すなわち 'チェッカーボードディザ' に非常によく似ていますが、チェッカーパターンではなく水平線を使っています。このディザパターンがどう見えるかを確認できるように、しきい値ディザリング画像のセットを直接利用する、かなり単純な自作の整列ディザを示します。

  magick gradient.png   dpat_hlines2x2.gif \
          -virtual-pixel tile  -fx 'u[(floor((n-1)*u)+1) % n]' dgrad_hlines2x2.gif

[IM Output]

見てのとおり、ディザパターンは何ら凝ったものではありません。"[-fx](https://imagemagick.org/command-line-options/#fx)" 関数はカラールックアップテーブル関数の変種、すなわち IM の 'ディザルックアップパターン' 型の関数です。そして 'tile' という "[-virtual-pixel](https://imagemagick.org/command-line-options/#virtual-pixel)" 設定があれば、この関数は使っているディザパターン画像のサイズを知る必要すらありません。 このように計算されたインデックスを使う "[-fx](https://imagemagick.org/command-line-options/#fx)" オペレータによる "[-virtual-pixel](https://imagemagick.org/command-line-options/#virtual-pixel)" の使用は、IM バージョン 6.2.9-2 より前は壊れていました。
このディザパターンのセットを、単純な影付き画像を使ってもう一度試してみましょう…
  magick shadow.png dpat_hlines2x2.gif  -channel A \
          -virtual-pixel tile  -fx 'u[floor((n-1)*u)+1].g' \
          shadow_dpat_hlines2x2.gif

[IM Output] [IM Output]

自作の整列ディザしきい値マップ

上記の自作ディザパターンは、得られる中でほぼ最も単純なディザパターンなので、高速な組み込みの "[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)" オペレータがそれを利用できるように、それを直接 XML しきい値マップに変換できます。これが最終的な XML 定義で、私はこれを自分の "$HOME" ディレクトリの個人的なしきい値マップファイル "~/.magick/thresholds.xml" に保存しました。

[IM Output]

XML 形式は非常に単純で、2x2 ピクセルのマップを定義しています。最初の黒い画像には値ゼロが与えられ、ピクセルがないので、ゼロ値は存在しません。中央の画像でオンになる(白くなる)ピクセルは '1' に設定され、残りのつまり 2 番目の画像のピクセルには '2' という値が与えられます。'divisor=' は、このディザパターンが表現する画像の数、つまり擬似色レベル(偽の色レベル)の数を定義するので、値は '3' です。これはピクセル値を分割し、そのピクセルをオンにする色レベルを定義します。そのため、上の 2 つのピクセルは 1/3 より大きい色についてオンになり、下の 2 つは 2/3 より大きい色値についてオンになります。つまり、各ピクセル値は 'しきい値' レベルを表しており、これがディザパターンがしきい値マップとも呼ばれる理由です。定義の残りの部分は、整列ディザオペレータでこのしきい値マップを参照するための名前(およびオプションのエイリアス)を定義しています。では、試してみましょう…

  magick gradient.png  -ordered-dither hlines2x2  od_hlines2x2.gif
  magick shadow.png  -channel A \
          -ordered-dither hlines2x2   shadow_hlines2x2.gif

[IM Output]
[IM Output] [IM Output]

見てのとおり、結果はそれなりに良いですが、結果を改善するために他のこともできます。マップ内のしきい値を調整することで、境界を変更し、色空間を 3 つの等しい領域に分割しないようにできます…

[IM Output]

色レベルを 10 の等しい区分に分割するために、除数を '10' に増やしたことに注目してください。それから、パターンが透明な端(黒)では 30% のしきい値から始まり、完全に不透明(白)では 90% になるように、しきい値設定を変更しました。そして、しきい値マップを変更した結果がこちらです。

  magick gradient.png  -ordered-dither hlines2x2a  od_hlines2x2a.gif
  magick shadow.png -channel A \
          -ordered-dither hlines2x2a  shadow_hlines2x2a.gif

見てのとおり、これは純粋な水平線をディザパターンとして使う半透明ピクセルの範囲を広げました。これにより、より良い影効果が得られます。ただし、おそらくここで使った例ほどぼやけていない影でのみ使うべきです。ただし、しきい値へのこの種の変更は非常にまれであることに注意してください。この場合は意図された用途には正当化されますが。基本的に、これはグラデーションを適切に定義していませんし、パターンの明暗の濃淡を許容していません。そのためには、より多くのピクセルと、より多くのパターンを持つ、はるかに複雑なしきい値マップを作る必要があります。

自作の水平線ディザ

ここでは、上で作成した単純な水平線ディザパターンをパターンのセットに拡張し、'オフ' から 'オン' へのより滑らかなグラデーションを生み出しました。これが結果です。

  montage dpat_hlines.gif   -filter box   -geometry 60x20+2+0 \
          -tile x1 -background none  -frame 2   dpat_hlines_images.gif
  magick gradient.png  dpat_hlines.gif  \
          -virtual-pixel tile  -fx 'u[(floor((n-1)*u)+1) % n]' \
          dgrad_dpat_hlines.gif
  magick shadow.png dpat_hlines.gif  -channel A \
          -virtual-pixel tile  -fx 'u[floor((n-1)*u)+1].g' \
          shadow_dpat_hlines.gif

[IM Output]
[IM Output]
[IM Output] [IM Output]

見てのとおり、今や 9 枚の 12x4 ピクセルの画像で構成されています。これは持ちうるすべてのピクセルパターンを表現しているわけではありませんが、線の効果を高めます。また、線の隙間を適切にずらすために、高さを 2 倍にしました。このディザパターンを使うもう 1 つの例を示します…

  magick -size 120x55 xc:white  -draw 'fill #777 ellipse 50,43 30,5 0,360' \
          -motion-blur 0x15+180   -blur 0x2      sphere_shadow.png
  magick sphere_shadow.png dpat_hlines.gif \
          -virtual-pixel tile  -fx 'u[(floor((n-1)*u)+1) % n]' \
          sphere_shadow_dither.gif
  magick sphere_shadow_dither.gif   -fill red  -stroke firebrick \
          -draw 'circle 35,25 35,5'     sphere_shadow_hlines.gif

[IM Output] [IM Output] [IM Output]

次のステップは、このディザパターンのセットを、複数の画像のセットではなく、単一のしきい値マップ画像に変換することです。これは、すべての画像を一緒にマージするいくつかの凝った画像操作を使って達成されます。 [IM Output]
[IM Output]


|

  magick -size 1x10 gradient: -flip -crop 1x1 +repage -delete 0,-1 \
          -scale 12x4\! null: \( dpat_hlines.gif -delete 0 \) \
          -alpha off -compose CopyOpacity -layers Composite \
          -reverse -compose Over -flatten -alpha off dmap_hlines.png

[IM Output]
'10' という値は、ディザパターン内の画像の数より 1 多く、一方 "-scale 12x4\!" はしきい値マップに変換されるディザパターンのサイズです。結果は、純粋な黒や白の色を含まないグレースケールのマップです。あるピクセルに使われるグレーレベルは、色レベルがそのグレー値以上であれば、そのピクセルがオンになるべきであることを意味します。つまり、各グレーレベルは、色値が黒から白に変わる 'しきい値' レベルなのです。この画像を別の見方で見ると、暗いピクセルは一般に、より多くの色レベルでそれらのピクセルがオンになる結果になります。一方、明るいピクセルは、画像の色が非常に明るくなったときにのみオンになります。これは画像が実際に見える様子のほぼ反転ですが、よく考えれば理にかなっています。また、マップには GIF 画像ではなく PNG 画像を使いました。保存する必要があるのは 1 枚の画像だけだからであり、さらに重要なことに、しきい値の 16 ビット品質レベルを保持しようとするためです。GIF は 8 ビットの色レベルしか扱えません。これで、たった 1 枚の画像と、各ピクセルをディザリングのしきい値画像(つまりマップ)に対して直接比較するずっと単純なしきい値比較だけで、画像をディザリングできます。

  magick gradient.png dmap_hlines.png \
          -virtual-pixel tile  -fx 'u>=v'   dgrad_dmap_hlines.gif

[IM Output] [IM Output]

しきい値マップがどれだけ単純になるか見てください。画像は 1 枚だけで、ディザリングされる各チャンネルについて、ピクセルあたり 1 回の直接比較を行うだけです。これにより、しきい値マップを使ったディザリングは非常に高速になります。完全な色の量子化よりはるかに高速です。この単純さこそが、ImageMagick とほとんどのグラフィックソフトウェアが、さまざまなディザパターンを保持するのにしきい値マップを使う理由です。 以上(または等しい)('>=')のテストは、IM バージョン 6.2.9-2 まで "[-fx](https://imagemagick.org/command-line-options/#fx)" オペレータに追加されていませんでした。これが問題になる場合は、上記で反転したテスト 'v<u' を使ってください。
しかし、この単純さは、ユーザーが複数の色レベルを使ってディザリングしたい場合には、はるかに複雑になります。これの概念実証は、IM のコア関数に組み込まれる前に、まずポスタライズされた整列ディザのページの例で割り出されました。マージされたしきい値画像ができたので、次に、上記の画像を、IM が直接読み込んで "[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)" オペレータが使える XML しきい値マップに変換する必要があります。これを行うには、画像が表現する 9 つのグレーレベルを表す数値として画像を出力する必要があります。これは、"NetPbm" 画像処理ソフトウェアを使った深度調整とともに、NetPBM または PBMplus 画像形式を使うのが最良です。このパッケージは一般に標準的な Linux のインストールに含まれているので、ほとんどの人はすでに持っているか、通常のソフトウェア配布元からインストールできます。"pnmdepth" の数値は、ここでもしきい値画像が含むグレーレベルの数です。
  magick dmap_hlines.png pgm:- | pnmdepth 9 | pnmnoraw > dmap_hlines.pgm

[IM Text]

上記の('P2' という画像マジック識別子以外の)すべての数値は、個人的な "thresholds.xml" ファイルに追加できる適切な 'しきい値マップ' を生成するのに必要な数値です。たとえば、これが上記から作成された結果のしきい値マップのエントリです。

[IM Output]

そして、このしきい値マップを使う例を示します。

  magick shadow.png  -channel A  -ordered-dither hlines   shadow_hlines.gif

[IM Output] [IM Output]

これが、画像の連なりから複雑なしきい値マップを生成する方法です。

シンボルパターンによるディザリング

さて、ほとんどのディザリング操作では、マルチイメージのパターンセットの代わりに単一のしきい値マップまたはしきい値画像を使えますが、だからといってマルチイメージのマップに独自の用途がないわけではありません。ルックアップ画像のセットを使って、一度に 1 つずつではなく、複数の領域を一度にタイリングできます。たとえば、単純な画像をスケーリングし、それから画像内の各ピクセルを特定のシンボルで置き換えることによってです。たとえば、ここでは非常に小さな 'eyes' 画像 [IM Output] を取り、個々のピクセルをさまざまなシンボルで置き換えて、元の画像の各ピクセルについてそうしたパターンを生成します。

  montage dpat_symbols.gif   -geometry +5+0 \
          -tile x1 -background none -mattecolor blue  -frame 3 \
          dpat_syms_images.gif
  magick eyes.gif -alpha off -colorspace sRGB -grayscale Average \
          -alpha off -scale 1600% -negate  \
          dpat_symbols.gif -virtual-pixel tile -fx 'u[floor(15.9999*u)+1]' \
          eyes_syms.gif

[IM Output]
[IM Output]

montage は、マルチイメージの GIF 画像が 'アニメーション化' されることなくその内容を見られるように、それを展開するのに使われています。使いたい "[-grayscale](https://imagemagick.org/command-line-options/#grayscale)" の強度手法は、通常の 'Rec709Luminance' から、より暗い 'Rec709Luma' まで調整したり、あるいは非線形の 'sRGB' カラースペースまたは線形の 'RGB' カラースペースのいずれかの 'average' を使ったりできます。色の最良の広がりを得るために、値の "[-gamma](https://imagemagick.org/command-line-options/#gamma)" スケーリングを調整することさえできます。可能性はたくさんあり、何が良いかは、選んだ実際の手法よりもシンボルの配置に依存します。上記の鍵は、入力画像の各色が一意のシンボルを生成するように何とか保証することであり、それを達成するのは非常にトリッキーです。この例は、より小さなコンピュータ画像から大きなスケールのアートワークを生成して、趣味人が従えるクロスステッチや編み物のガイドを作成するのに使えます。この技法を使って、グレースケール画像をタイリング用のカラー画像のセットでタイリングできます。その結果は、多くの古いコンピュータ戦争ゲームで見られる風景マップに少し似ています。

  montage dpat_map.gif   -geometry +5+0 -tile x1  -background none  \
          dpat_map_images.gif
  magick -seed 100 \
          -size 200x200 plasma:'gray(50%)-gray(50%)' -blur 0x15 \
          -channel G -auto-level +channel -set colorspace sRGB \
          dpat_map.gif -virtual-pixel tile  -fx 'u[floor(5.999*u.g)+1]' \
          map.gif

[IM Output]
[IM Output]

FX のインデックスルックアップに使われているのは実際には線形 RGB データであるにもかかわらず、IM がそのグレースケール画像を(タイル画像と同様に)すでに最終的な sRGB カラースペースにあるものとみなすように保証する必要があったことに注意してください。これがないと、結果の 'マップ' は森林の風景に偏り、水域の可能性がほとんどなくなってしまいます。見てのとおり、タイルには任意の画像のセットを使えます。画像は互いに揃っている必要すらなく、同じサイズのタイルである必要すらありません。もちろん、3 つの青い '海' のタイルの場合のように、タイルが同じサイズで互いに密接に関連していれば、タイル状のパターンはあるタイル領域から別のタイル領域へと '流れる' ことができます。タイルを数字の画像に置き換えれば、一種の数字で塗り絵をするガイドも生成できます。ただし、異なる領域に境界を付けるには、いくらか余分な処理が必要かもしれません。これは練習問題として残します。あなたの解決策を私にメールしてくれれば、この技法の考案者として IM Examples にあなたの名前を載せることができます。


整列ディザのランダムな注記と将来の可能性

作成中

少数の色を使った整列ディザ

小さな画像に少数の色を使う場合、IM のヒルベルト曲線誤差補正ディザのような擬似ランダムなディザ、あるいはより単純な Floyd-Steinberg 誤差補正ディザ(上記の誤差補正ディザを参照)でさえ、見るに堪えない結果を生み出します。理想的には、低色数で小さなアイコンのような画像には整列ディザを使って、ずっと見栄えの良い結果を生み出すべきです。しかし現時点では、IM の整列ディザは '固定された' 数学的に生成されたカラーテーブルしか使えず、'最良の' 色の集まりは使えません。

任意の色のマップを使った整列ディザ

整列ディザリングに特定の色のセットを使えるようにするアルゴリズムが存在します。基本的に、整列ディザアルゴリズムが生成できる '擬似色'(3 色のディザリングを含むことがあります)を、与えられたカラーマップに追加して 'それを埋める' のです。それから、画像の個々のピクセルをこの '拡張されたカラーマップ' に 'マッピング' できます。その最初の(特定の擬似色への)マッピングから、その擬似色を生成するしきい値マップから実際の色を選び、こうしてその色の領域を、ひいては画像全体を、与えられた色のセットに整列ディザリングできます。アイコン、そして今では GIF アニメーションを背景とする私としては、任意色の整列ディザが実装されるのをぜひ見たいのですが、固定された色のセットで整列ディザを行う方法についての実用的な参考資料はまだ見つけられていません。