1

Python2.7.3とPIL1.1.7を使用してWindows7プラットフォームで開発しています。

テキストを含む一連の画像を生成するPythonスクリプトを作成しようとしています。テキストを折り返して任意の境界ボックスに収める必要があるため、アルファ透明レイヤーをオンにして、白いRGBA背景画像にテキストを描画するメソッドを作成しました。問題を単純化するために、問題を説明する小さなPythonスクリプトを作成しました。

import Image,ImageDraw,ImageFont
import webbrowser

# sample text and font
text = "The text quality will degrade with the paste operation."
verdana_font = ImageFont.truetype("verdana.ttf", 20)

# get the line size
text_width, text_height = verdana_font.getsize(text)

# create a blank canvas with extra space between lines
blank_canvas = Image.new('RGB', (text_width + 10, text_height * 10 + 5 * 10), (255, 255, 255))

# create a blank RGBA canvas for the drawn text
text_canvas = Image.new('RGBA', (text_width, text_height), (255, 255, 255, 0))

draw = ImageDraw.Draw(text_canvas)

# draw the text onto the text canvas  
draw.text((0,0), text, font = verdana_font, fill = "#000000")

# print 10 lines
for x in range(0,10):

    # calculate the coordinates for the paste operation and debug 
    coordinates = (5, 5 + (x * (5 + text_height)))
    print "x = %d | coordinates = %r" % (x, coordinates)

    # paste the text onto the blank canvas
    blank_canvas.paste(text_canvas, coordinates, text_canvas)

    # create a temporary canvas
    temp_canvas = Image.new('RGBA', (text_width, text_height), (0, 0, 0, 0)) 

    # paste the text canvas onto the temp canvas using the png alpha layer for transparency
    temp_canvas.paste(text_canvas, (0,0), text_canvas)

    # swap the canvases
    text_canvas = temp_canvas

# save the blank canvas to a file
blank_canvas.save("paste-degradation.png", "PNG")

# open the image up to see the paste operation's image degradation
webbrowser.open("paste-degradation.png")

テキストが新しい「一時的な」キャンバスに貼り付けられるたびに、描画されるテキストの画質はますます悪化します。上記のコードは、次のような画像を生成します。

テキスト品質の低下

コードに問題がありますか?またはPILにバグがありますか?

4

1 に答える 1

2

問題は、draw.text()の動作が少し予期しないことです。

draw.text()は、いくつかのピクセルをfill(テキストの内側にあるピクセル)に設定し、他のピクセル(テキストの外側にあるピクセル)には触れないようにして、テキストを描画します。ただし、ピクセルがテキストの25%の部分にあることがわかった場合、draw.text()は、新しいピクセルをfill古い値の25%と75%に設定するだけです。ただし、このような比率は、RGBAの4つのコンポーネントすべてに個別に適用されます。この例では、背景は(255、255、255、0)であり、fill(0、0、0、255)です。したがって、テキスト内の25%のピクセルは(192、192、192、64)になります。 。

しかし、これは直感的な結果ではないと私は主張します。直感的な結果は(0、0、0、64)になります。このようなテキストを、たとえば完全に赤い画像に貼り付けた場合でも、上のピクセルは明るい灰色(192、192、192)の25%を占めることになります。言い換えると、灰色の境界線が表示され、その間に黒、赤、および色のみが表示されます。

(実際、上記の説明は単純すぎます。背景を(0、0、0、0)に設定しても効果はありません。これは、その色が実際には(255、255、255、0)と同等であるためと思われます。完全に透過的です。さらに、同じアルゴリズムがcanvas.paste(img, (0,0), img)呼び出しで使用されているようです。)

これを修正する方法は、テキストから描画された画像のアルファバンドのみを使用することです。つまり、に置き換えtemp_canvas.paste(text_canvas, (0,0), text_canvas)ますtemp_canvas.paste("#000000", (0,0), text_canvas)

于 2013-01-21T18:12:46.130 に答える