web-dev-qa-db-ja.com

PILを使用して画像にテキストを追加する

画像を読み込むアプリケーションがあり、ユーザーがクリックすると、この画像のテキスト領域が表示され(jqueryを使用)、ユーザーは画像にテキストを書き込むことができます。画像に追加する必要があります。

いくつかの研究を行った後、PIL(Python Imaging Library)がこれを助けることができると考えました。そこで、いくつかの例を試して、どのように機能するかを確認し、画像にテキストを書き込むことに成功しました。しかし、Python Shellを使用してWeb環境で試してみると、いくつかの違いがあると思います。 textareaのテキストはpxで非常に大きいことを意味します。 PILをtextareaのテキストと同じサイズのテキストに使用するにはどうすればよいですか?

テキストは複数行です。 PILを使用して、画像内で複数行にするにはどうすればよいですか?

PILを使用するよりも良い方法はありますか?これが最良の実装である場合、私は完全にはわかりません。

html:

<img src="images/test.jpg"/>

編集中の画像

var count = 0;
$('textarea').autogrow();
$('img').click(function(){
    count = count + 1;
    if (count > 1){
        $(this).after('<textarea />');
        $('textarea').focus();
    }   
});

テキストエリアを追加するjquery。また、テキスト領域はposition:absoluteおよびfixed sizeです。

画像内のテキストエリアの座標を取得できるように、フォーム内に配置する必要がありますか?ユーザーがクリックしたときに画像にテキストを書き込み、画像に保存したい。

80
Apostolos

ImageFontPILで利用可能なモジュールは、テキストのフォントサイズの問題を解決するのに役立つはずです。どのフォントタイプとサイズが適切かを確認し、次の機能を使用してフォント値を変更します。

# font = ImageFont.truetype(<font-file>, <font-size>)
# font-file should be present in provided path.
font = ImageFont.truetype("sans-serif.ttf", 16)

したがって、コードは次のようになります。

from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw 

img = Image.open("sample_in.jpg")
draw = ImageDraw.Draw(img)
# font = ImageFont.truetype(<font-file>, <font-size>)
font = ImageFont.truetype("sans-serif.ttf", 16)
# draw.text((x, y),"Sample Text",(r,g,b))
draw.text((0, 0),"Sample Text",(255,255,255),font=font)
img.save('sample-out.jpg')

フォントサイズを計算するために余分な努力が必要になる場合があります。ユーザーがTextAreaで提供したテキストの量に基づいて変更する場合。

テキストの折り返し(複数行)を追加するには、1行に何文字入力できるかを大まかに考えてから、おそらくテキストの前処理関数を記述できます。この文字の前の空白を改行に変換します。

146
lalit

プロジェクトのルートにディレクトリ「fonts」を作成し、そこにフォント(sans_serif.ttf)ファイルを配置できます。その後、次のようなものを作成できます。

fonts_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'fonts')
font = ImageFont.truetype(os.path.join(fonts_path, 'sans_serif.ttf'), 24)
13
svpp

さらに最小限の例(「Hello world!」を黒で描画し、画像の左上にデフォルトのフォントを使用):

...
from PIL import ImageDraw
...
ImageDraw.Draw(
    image  # Image
).text(
    (0, 0),  # Coordinates
    'Hello world!',  # Text
    (0, 0, 0)  # Color
)
6
Solomon Ucko

まず、フォントタイプをダウンロードする必要があります。たとえば、 https://www.wfonts.com/font/Microsoft-sans-serif です。

その後、次のコードを使用してテキストを描画します。

from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw 
img = Image.open("filename.jpg")
draw = ImageDraw.Draw(img)
font = ImageFont.truetype(r'filepath\..\sans-serif.ttf', 16)
draw.text((0, 0),"Draw This Text",(0,0,0),font=font) # this will draw text with Blackcolor and 16 size

img.save('sample-out.jpg')
3
Kumar S

Pillowでは、ImageDrawモジュールを使用して画像を描画することもできます。線、点、楕円、長方形、円弧、ビットマップ、和音、パイスライス、多角形、図形、テキストを描くことができます。

from PIL import Image, ImageDraw
blank_image = Image.new('RGBA', (400, 300), 'white')
img_draw = ImageDraw.Draw(blank_image)
img_draw.rectangle((70, 50, 270, 200), outline='red', fill='blue')
img_draw.text((70, 250), 'Hello World', fill='green')
blank_image.save('drawn_image.jpg')

new()メソッドを使用してImageオブジェクトを作成します。これは、ロードされたイメージのないImageオブジェクトを返します。次に、画像を保存する前に、画像に長方形とテキストを追加します。

1
Tamil Selvan S

他の回答で言及されていないことの1つは、テキストサイズの確認です。テキストが画像に収まることを確認する(たとえば、サイズが大きすぎる場合はテキストを短くする)か、テキストを描画する位置を決定する(たとえば、テキストの中央を揃える)必要があります。 Pillow/PILには、ImageFontを使用した方法とImageDrawを使用した方法の2つの方法でテキストサイズを確認できます。以下に示すように、フォントは複数の線を処理しませんが、ImageDrawは処理します。

In [28]: im = Image.new(mode='RGB',size=(240,240))                                                            
In [29]: font = ImageFont.truetype('arial')
In [30]: draw = ImageDraw.Draw(im)
In [31]: t1 = 'hello world!'
In [32]: t2 = 'hello \nworld!'
In [33]: font.getsize(t1), font.getsize(t2) # the height is the same
Out[33]: ((52, 10), (60, 10)) 
In [35]: draw.textsize(t1, font), draw.textsize(t2, font)  # handles multi-lined text
Out[35]: ((52, 10), (27, 24)) 
0
lange