Ghostscript でラスタライズ(#3:ダウンスケール)

2022年5月28日

Ghostscript でジャギーを抑える別の方法として、-dDownScaleFactor を使用するテがあります。 -dGraphicsAlphaBits や -dTextAlphaBits はアンチエイリアス処理に特化したオプションです。 これに対して -dDownScaleFactor は、ラスタライズした画像に対してさらに縮小処理をかけます。 縮小処理に 面積平均法(または平均画素法とも; area averaging)を使用しているようなので、結果的にジャギーが抑えられた画像が得られることになります。 例えば -DownScaleFactor=3 を指定すると、ラスタライズされた画像はさらに 1/3 に縮小されます。設定値の範囲は1〜8の整数です。 設定値に2以上を指定した場合は、最終的な解像度は -r で指定した解像度よりも小さくなります。 よって縮小を見込んであらかじめ大きめのラスタライズ解像度を指定することになり、以下の計算式で求めることができます。  [-r の設定値] = [最終解像度] × [-dDownScaleFactor の設定値] それでは、-dDownScaleFactor の値によって見た目がどの程度変わるのかを実験してみましょう。
$ gs -dDownScaleFactor=1 -r72 -dSAFER -sDEVICE=png16m -o out1.png logo-ghost.pdf
$ gs -dDownScaleFactor=2 -r144 -dSAFER -sDEVICE=png16m -o out2.png logo-ghost.pdf
$ gs -dDownScaleFactor=3 -r216 -dSAFER -sDEVICE=png16m -o out3.png logo-ghost.pdf
$ gs -dDownScaleFactor=4 -r288 -dSAFER -sDEVICE=png16m -o out4.png logo-ghost.pdf
$ gs -dDownScaleFactor=5 -r360 -dSAFER -sDEVICE=png16m -o out5.png logo-ghost.pdf
$ gs -dDownScaleFactor=6 -r432 -dSAFER -sDEVICE=png16m -o out6.png logo-ghost.pdf
$ gs -dDownScaleFactor=7 -r504 -dSAFER -sDEVICE=png16m -o out7.png logo-ghost.pdf
$ gs -dDownScaleFactor=8 -r576 -dSAFER -sDEVICE=png16m -o out8.png logo-ghost.pdf
最終的な解像度を 72ppi に固定するため、-dDownScaleFactor の値に応じて -r を変更しています。 その結果は以下のとおりになりました。
-dDownScale
Factor
-rGhostscript
(原寸)
Photoshop
(原寸)
Ghostscript
(拡大:4倍)
Photoshop
(拡大:4倍)
172logo-ghost.dsf1logo-ghost.aa.ps-72logo-ghost.dsf1.x4logo-ghost.aa.ps-72.x4
2144logo-ghost.dsf2logo-ghost.aa.ps-72logo-ghost.dsf2.x4logo-ghost.aa.ps-72.x4
3216logo-ghost.dsf3logo-ghost.aa.ps-72logo-ghost.dsf3.x4logo-ghost.aa.ps-72.x4
4288logo-ghost.dsf4logo-ghost.aa.ps-72logo-ghost.dsf4.x4logo-ghost.aa.ps-72.x4
5360logo-ghost.dsf5logo-ghost.aa.ps-72logo-ghost.dsf5.x4logo-ghost.aa.ps-72.x4
6432logo-ghost.dsf6logo-ghost.aa.ps-72logo-ghost.dsf6.x4logo-ghost.aa.ps-72.x4
7504logo-ghost.dsf7logo-ghost.aa.ps-72logo-ghost.dsf7.x4logo-ghost.aa.ps-72.x4
8576logo-ghost.dsf8logo-ghost.aa.ps-72logo-ghost.dsf8.x4logo-ghost.aa.ps-72.x4
※ Photoshop の画像は -dDownScaleFactor の値に関わらずすべて同じ画像です。 この結果を見ると、原寸表示では -dDownScaleFactor=2 でも充分実用になりそうです。 拡大表示で Photoshop と比較した場合は -dDownScaleFactor=4 あたりから Photoshop と遜色無くなる、といったところでしょうか? それ以上の設定値では、ハッキリとした違いは見つけ難いようです。 おそらく -r の値が大きくなるぼど処理時間がかかる気がするので(この程度の pdf データならば体感的な違いはありませんでした)、 目的に応じた -r と -dDownScaleFactor の組み合わせを使っていきましょう。 その4
参考までにダウンスケール処理部のソースリストを抜粋しておきます。(8bit-RGB 専用のダウンスケール処理です)
/* RGB downscale (no error diffusion) code */

static void down_core24(gx_downscaler_t *ds,
                        byte            *outp,
                        byte            *in_buffer,
                        int              row,
                        int              plane,
                        int              span)
{
    int   x, xx, y, value;
    int   pad_white;
    byte *inp;
    int   width  = ds->width;
    int   awidth = ds->awidth;
    int   factor = ds->factor;
    int   div    = factor*factor;

    pad_white = (awidth - width) * factor * 3;
    if (pad_white < 0)
        pad_white = 0;

    if (pad_white)
    {
        inp = in_buffer + width*factor*3;
        for (y = factor; y > 0; y--)
        {
            memset(inp, 0xFF, pad_white);
            inp += span;
        }
    }

    inp = in_buffer;
    {
        /* Left to Right pass (no min feature size) */
        const int back  = span * factor - 3;
        const int back2 = factor * 3 - 1;
        for (x = awidth; x > 0; x--)
        {
            /* R */
            value = 0;
            for (xx = factor; xx > 0; xx--)
            {
                for (y = factor; y > 0; y--)
                {
                    value += *inp;
                    inp += span;
                }
                inp -= back;
            }
            inp -= back2;
            *outp++ = (value+(div>>1))/div;
            /* G */
            value = 0;
            for (xx = factor; xx > 0; xx--)
            {
                for (y = factor; y > 0; y--)
                {
                    value += *inp;
                    inp += span;
                }
                inp -= back;
            }
            inp -= back2;
            *outp++ = (value+(div>>1))/div;
            /* B */
            value = 0;
            for (xx = factor; xx > 0; xx--)
            {
                for (y = factor; y > 0; y--)
                {
                    value += *inp;
                    inp += span;
                }
                inp -= back;
            }
            inp -= 2;
            *outp++ = (value+(div>>1))/div;
        }
    }
}

使用バージョン: Photoshop CS5(12.0 x64) / Illustrator CS5(15.0.0) / Ghostscript 9.16