ImageMagick の例 --
アンチエイリアシング

目次
ImageMagick の例 はじめに & 目次
アンチエイリアシング入門
特定の色のみを使用した描画
細いビットマップ円の描画
アンチエイリアシングと塗りつぶしの問題
アンチエイリアシングは、ImageMagick 内のすべての描画操作の主要な部分です。しかし、残念ながら多くの問題を引き起こす可能性もあります。このページでは、これらの問題と解決策について説明します。

アンチエイリアシング入門

ImageMagick は、画像を描画する際に、非常に特殊な方法で行います。「アンチエイリアシング」と呼ばれる操作で描画します。例として、透明な背景に画像を描画し、画像の小さな部分を拡大して何が起こっているかを見てみましょう。

   magick -size 80x80 xc:none \
            -fill white  -draw "circle 40,40 15,20" \
            -fill black  -draw "line 5,30 78,2"    drawn.png
    magick drawn.png -crop 10x10+50+5 +repage -scale 80x80  drawn_mag.png
 
[IM Output] ==> [IM Output]
上記の画像は、IM に使用するよう指示した「白」、「黒」、および「透明」の 3 色のみで構成されていると考えるかもしれません。しかし、画像を拡大すると、さまざまな色の範囲があることがわかります。ImageMagick は、このようにすることで、「アンチエイリアシング」と呼ばれる手法を使用して、画像をより滑らかに、より見栄え良くします。これは、オブジェクトのエッジピクセルを色の混合、さらには透明度で塗りつぶして、オブジェクトを滑らかに見せることを意味する専門用語です。アンチエイリアシングが行われなかった場合、すべての描画オブジェクトのエッジは、「ジャギー」と呼ばれる階段状の効果になります。ここでは、画像をもう一度描画しますが、今回は IM に "+antialias" を使用して、自動アンチエイリアシング操作をオフにするように指示しました。

   magick -size 80x80 xc:none +antialias \
            -fill white  -draw "circle 40,40 15,20" \
            -fill black  -draw "line 5,30 78,2"    drawn_jaggies.png
    magick drawn_jaggies.png -crop 10x10+50+5 +repage -scale 80x80 \
            drawn_jaggies_mag.png
 
[IM Output] ==> [IM Output]
今回は、画像は実際に 3 色のみで構成されています。しかし、結果はあまり良くありません。最新の IM では、1 行のピクセルが階段状に描画されます。古い IM では、線もかなり太く表示され、さらに悪化していました。基本的に、これは通常行いたいことではありません。「ジャギー」効果とも呼ばれる「エイリアシング」の階段状の現象は、IM が回避しようとしていたものです。ただし、特定の色が必要な場合は、これをそのまま受け入れるか、他の手法(カラー量子化など)を使用して特定の色のみを使用するようにする必要があります。実際には、2 つの形式のアンチエイリアシングが発生していることに注意してください。1 つ目は、画像内の白と黒の色をブレンドして、さまざまな色の濃淡(この場合は灰色)を生成することです。もう 1 つの形式は、色と透明度をブレンドして、画像に半透明のピクセルを生成することです。後者は覚えておく必要があります。多くの画像形式(GIF など)は半透明のピクセルを処理できないため、そのようなピクセルは完全に不透明または完全に透明になります。GIF ブール値の透明度の例では、このような形式で保存する際に半透明のピクセルの処理を制御する方法を示しています。

まとめ

アンチエイリアシングは、あらゆる種類の画像描画において非常に重要であり、常に心に留めておくべきことです。IM アンチエイリアシングによって生成される混合色と半透明のピクセルを考慮しないと、独自の画像作成が一部の形式で非常に悪く見える可能性があります。これは、広く普及している「GIF」形式など、半透明のピクセルを許可しない画像形式で画像を作成する場合にさらに重要になります。この問題の対処方法については、GIF ブール値の透明度を参照してください。IM は色と透明度のアンチエイリアシングは非常に優れていますが、実際には純粋な「エイリアス」ピクセル(たとえば、特定のカラーマップに一致させるため)の描画は非常に苦手です。これは IM の今後のリリースで重点的に取り組まれると聞いています。

特定の色のみを使用した描画

建設中
アンチエイリアシングなしで描画し、正確な色で画像を生成するより良い方法。つまり、「インデックス付き画像」の場合です。具体的には、透明なキャンバスに描画し、アルファチャネルをしきい値処理してからオーバーレイします。そのため、完全に不透明なピクセルのみが描画されます。

細いビットマップ円の描画

ここでは、IM を使用してビットマップ化された「細い線」の円を描画する方法を見ていきます。通常、これは、一般にブレーゼンハムの円アルゴリズムとして知られているビットマップ円描画アルゴリズムを使用して行われますが、より正確には中点円アルゴリズムとして知られています。残念ながら、これは ImageMagick では使用できません。また、完全にアンチエイリアスされた描画環境では不要なため、使用できない可能性があります。円の描画の別の方法として、後で説明しますが、モルフォロジーを使用して、特別なリングカーネルを使用して単一のピクセルを「拡張」する方法があります。
たとえば、通常の IM で円を描画すると、多くの灰色のアンチエイリアシング色が生成され、円が滑らかに表示されます。

  magick -size 15x15 xc: -fill none -stroke black \
          -draw 'translate 7,7 circle 0,0 5,0' \
          -scale 500%  circle_antialiased.gif
[IM Output]
ただし、アンチエイリアシングをオフにするだけで、円と線が細い「ビットマップ」線ではなくなります。

  magick -size 15x15 xc: -fill none -stroke black +antialias \
          -draw 'translate 7,7 circle 0,0 5,0' \
          -scale 500%  circle_aliased.gif
[IM Output]
行う必要があるのは、デフォルトで 1 ピクセル幅の "-strokewidth" を 0.5 ピクセル幅などのより小さい値に調整することです。

  magick -size 15x15 xc: -fill none -stroke black +antialias \
          -strokewidth 0.5   -draw 'translate 7,7 circle 0,0 5,0' \
          -scale 500%  circle_thin_stroke.gif
[IM Output]
良くなりましたが、まだ完全ではありません。ストロークの幅を小さくしすぎることもできます。特に、奇数サイズの半径の場合です。

  magick -size 15x15 xc: -fill none -stroke black +antialias \
          -strokewidth 0  -draw 'translate 7,7 circle 0,0 5,0' \
          -scale 500%  circle_zero_stroke.gif
[IM Output]
これは、整数の実際のピクセル位置を中心とした 5 ピクセルの円の適切なソリューションです。

  magick -size 15x15 xc: -fill none -stroke black +antialias \
          -strokewidth 0.4  -draw 'translate 7,7 circle 0,0 5,0' \
          -scale 500%  circle_perfect.gif
[IM Output]
しかし、多くの実験の後、すべての半径と中心に有効な "-strokewidth" は見つかりませんでした。特に、中心からわずかにずれている円の場合です。
すべての状況に最適な解決策はありません
たとえば、ピクセルまたはピクセル境界の中心にないこの円は、上部に隙間があるだけでなく、下部が厚すぎます!

  magick -size 15x15 xc: -fill none -stroke black +antialias \
          -strokewidth 0.47  -draw 'translate 7,7.3 circle 0,0 5,0' \
          -scale 500%  circle_bad_stroke.gif
[IM Output]
これは、特定の半径の細い 1 ピクセル幅の円を生成するための適切な "-strokewidth" の表です。使用するのに最適な値は、円が*実際の*ピクセル(「 5 , 5 」など)の中心にあるか、*半分*のピクセル境界(「 5.5 , 5.5 」など)の中心にあるかによって異なることに注意してください。
円の半径 実際のストローク幅 半分のストローク幅
1 0.3   0.3 ¶
1.5   0.5 ¶ 0.3
2 0.3   0.3 §
2.5   0.5 ¶   0.3 ¤
3   0.3 ¤ 0.3
3.5 0.5   0.3 ¤
4   0.5 § 0.3
4.5 0.5 0.3
5 0.4 0.3
5.5   0.5 ¶ 0.3
6 0.3   0.5 §
6.5 0.5 0.43
7 0.5 0.434
7.5   0.5 §   0.5 §
8 0.4 0.5
¤ 非常に良い小さな円
§ 理想的な幅は見つかりません
¶ 円は非常に悪い
補足:画像上で円を中心にするには、描画座標(ピクセル座標)で (サイズ-1)/2 です

アンチエイリアシングと塗りつぶしの問題

IM のアンチエイリアシング機能により、塗りつぶし("-draw color floodfill")は、アンチエイリアシング効果のある画像で使用すると問題が発生します。「JPG」画像形式から読み込まれた画像でも同様の問題が発生します。基本的に、IM のほとんどのオブジェクトはアンチエイリアスされている(または「JPG」形式の画像ファイルから読み込まれている)ため、描画されたオブジェクトのエッジ付近の色は、塗りつぶしの置換に使用する特定の色とほとんど同じではありません。つまり、アンチエイリアシングを完全に回避していない限り、塗りつぶしは塗りつぶし対象の領域の端まで塗りつぶされません。本質的に、塗りつぶし、または色の置換でさえ、アンチエイリアシングを理解しておらず、アンチエイリアシング手法自体を使用していません。その結果、塗りつぶしは、一般に、塗りつぶし対象の領域の端にあるピクセルを見逃します。たとえば、ここでは、典型的な塗りつぶし操作を実行します。円を描画し、パターンで塗りつぶそうとします...

    magick -size 60x60 xc:lightblue -strokewidth 2 \
            -fill none -stroke red -draw "circle 30,30 5,30" \
            -tile tile_weave.gif  -draw "color 30,30 floodfill" \
            tile_fill_1.gif
    magick tile_fill_1.gif -crop 10x10+35+4 +repage -scale 80x80 \
            tile_fill_1_mag.gif
 
[IM Output] [IM Output]
画像の拡大部分でわかるように、「オフカラー」のピクセルの線が塗りつぶし操作によって完全に欠落していました。これらのピクセルの色が、塗りつぶし対象の領域とまったく同じではなかったためです。これを改善する 1 つの方法は、使用するパターンと一致する色で、塗りつぶし対象の領域を事前に塗りつぶしておくことです。パターンはまだ領域を完全に塗りつぶしませんが、少なくともそれほど悪くは見えないでしょう。

    magick -size 60x60 xc:lightblue -strokewidth 2 \
            -fill black -stroke red  -draw "circle 30,30 5,30" \
            -tile tile_weave.gif  -draw "color 30,30 floodfill" \
            tile_fill_2.gif
    magick tile_fill_2.gif -crop 10x10+35+4 +repage -scale 60x60 \
            tile_fill_2_mag.gif
 
[IM Output] [IM Output]
これを行う別の方法は、高いファジー係数で領域をパターンで塗りつぶし、パターンがエッジピクセルを見逃すことなく、端まで領域を完全に塗りつぶすように強制することです。

    magick -size 60x60 xc:lightblue -strokewidth 2 \
            -fill none -stroke red  -draw "circle 30,30 5,30" \
            -fuzz 35% -tile tile_weave.gif -draw "color 30,30 floodfill" \
            tile_fill_3.gif
    magick tile_fill_3.gif -crop 10x10+35+4 +repage -scale 60x60 \
            tile_fill_3_mag.gif
 
[IM Output] [IM Output]
このような高い「ファジー係数」、または細すぎる境界線は、塗りつぶしパターンが定義された領域から「漏れる」可能性があることに注意してください。塗りつぶし操作を使用する場合は、常に注意が必要です。このため、一般的な解決策としては実際にはお勧めしません。
これに伴う問題は、塗りつぶしは本質的にアンチエイリアシング自体を使用しないため、塗りつぶされた領域のエッジが「ジャギー」またはエイリアス効果の影響を受けることです。画像の描画を別々の手順に分けることで、その状況を改善できます。色の付いた円を作成し、塗りつぶしてから、境界線を描画します。

    magick -size 60x60 xc:lightblue -fill black -draw "circle 30,30 5,30" \
            -tile tile_weave.gif -draw "color 30,30 floodfill" +tile \
            -fill none -stroke red  -strokewidth 2 -draw "circle 30,30 5,30" \
            tile_fill_4.gif
    magick tile_fill_4.gif -crop 10x10+35+4 +repage -scale 60x60 \
            tile_fill_4_mag.gif
 
[IM Output] [IM Output]
これは、塗りつぶしを改善する簡単な方法の 1 つです。もう 1 つは、形状のオーバーレイを使用することですが、これは難しい方法です。後で、既存の画像への同様の変更について検討します。もちろん、塗りつぶし対象の領域を自分で描画し、既存の画像を使用していない場合は、元の描画操作に塗りつぶしパターンを指定することで塗りつぶしを回避するのが理想的な解決策です。

    magick -size 60x60 xc:lightblue -strokewidth 2 \
            -tile tile_weave.gif -stroke red -draw "circle 30,30 5,30" \
            tile_fill_5.gif
    magick tile_fill_5.gif -crop 10x10+35+4 +repage -scale 60x60 \
            tile_fill_5_mag.gif
 
[IM Output] [IM Output]

FUTURE:  anti-aliasing issues on pre-exsiting images (especially JPG format).

For Example Recoloring and overlaying text or diagram image onto a color
or background.

Also re-adding transparency to GIF files, and rescaled JPEGs for icon use.

Smoothing or anti-alising images with limited color set
Specifically bitmap (pure black and white) images.

First anti-aliasing does not work on bitmap images.

Anti-aliasing involves using a mix of colors and transparences to try and
smooth the 'stair case' or 'jaggies' effect of slanted lines and color
boundaries.  If only two colors are available no anti-aliasing can NOT happen!

The image must be converted from B&W or grey scale at the minimum before
anti-aliasing can be used.

A simple way to smooth edges is to use a small amount of blur after reading in
a B&W image or an image with a tiny pallette size.

EG:   magick image.xbm  -blur 0x.3  smoothed_image.png