Добавить текст на изображение с помощью PIL


94

У меня есть приложение, которое загружает изображение, и когда пользователь щелкает его, появляется текстовая область для этого изображения (с использованием jquery), где пользователь может написать текст на изображении. Который должен быть добавлен в Image.

Проведя небольшое исследование, я решил, что PIL(Python Imaging Library) может мне в этом помочь. Итак, я попробовал несколько примеров, чтобы увидеть, как это работает, и мне удалось написать текст на изображении. Но я думаю, что есть некоторая разница, когда я пробую его использовать Python Shellи в веб-среде. Я имею в виду, что текст в текстовой области очень большой в пикселях. Как я могу добиться того же размера текста при использовании PIL, что и в текстовом поле?

Текст многострочный. Как я могу сделать его многострочным и на изображении, используя 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 для добавления текстового поля. Также текстовая область имеет положение: абсолютный и фиксированный размер.

Должен ли я разместить его внутри формы, чтобы я мог получить координаты текстового поля на изображении? Я хочу писать текст на изображении, когда пользователь нажимает, и сохранять его на изображении.


Почему вы хотите писать текст на изображении, используя PIL (и я не уверен, помогает ли PIL в этом). Разве для вас не достаточно отображать текст в наложении, которое чаще всего используется в ползунках.
лалит

1
Мне он нужен для проекта, я хочу, чтобы изображение было сохранено. Пил может рисовать текст на изображении с помощью ImageDraw, не знаю, есть ли другой способ.
Апостолос

Это будет полезно. Если вы предоставите код Python, который используете?
лалит

еще не реализовано в django. Я попытался посмотреть, как PIL работает в интерактивной консоли Python. Хотите сначала проверить, работает ли он, а затем перенести его в Django.
Апостолос

Какой символ $ в вашем коде?
Mugen

Ответы:


173

Я думаю, что модуль ImageFont, доступный в, PILдолжен быть полезен в решении проблемы с размером шрифта текста. Просто проверьте, какой тип и размер шрифта вам подходит, и используйте следующую функцию для изменения значений шрифта.

# 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
Это моя первоначальная мысль. Так что, чтобы мои шрифты работали в определенной папке на моем веб-сервере? Думаю, да. Перенос текста? Есть ли стандартный способ или я должен его реализовать?
Апостолос

Вы можете хранить файл шрифта где угодно на вашем веб-сервере. Просто убедитесь, что указанный вами путь правильный.
лалит

7
@lalit Я пробовал ваш код на машине с Windows, и у меня возникла ошибка шрифта self.font = core.getfont(file, size, index, encoding) IOError: cannot open resource. Как я могу указать путь к файлу шрифта?
LWZ

3
@LWZ, чтобы запустить вышеуказанный код, просто убедитесь, что файл шрифта находится в текущем каталоге, в котором вы выполняете вышеуказанный код. Если вы используете его в своей программе, просто укажите полный путь к файлу, например, «C: \ Windows \ Fonts \ sans-serif.ttf». Еще одна вещь, в которой вам нужно убедиться, - это предоставить соответствующие разрешения на чтение файла.
lalit

3
font = ImageFont.truetype ("./ arial.ttf", 30); draw.textsize (msg, font = font);
WeizhongTu

16

Вы можете создать каталог «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)

15

Еще более минималистичный пример (рисует «Hello world!» Черным цветом со шрифтом по умолчанию в левом верхнем углу изображения):

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

8

Сначала вам нужно загрузить тип шрифта ... например: 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')

5

С помощью 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')

мы создаем объект Image с помощью метода new (). Это возвращает объект Image без загруженного изображения. Затем мы добавляем прямоугольник и текст к изображению перед его сохранением.


4

Одна вещь, не упомянутая в других ответах, - это проверка размера текста. Часто требуется убедиться, что текст соответствует изображению (например, укоротить текст, если он слишком большой), или определить место для рисования текста (например, выровненный текст по центру вверху). Pillow / PIL предлагает два метода проверки размера текста: один с помощью ImageFont, а другой с помощью ImageDraw. Как показано ниже, шрифт не обрабатывает несколько строк, в отличие от 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)) 

Спасибо, что подчеркнули эту разницу. Я действительно искал текст нужного размера в многострочном формате.
fcole90

-9

Чтобы добавить текст в файл изображения, просто скопируйте / вставьте код ниже

<?php
$source = "images/cer.jpg";
$image = imagecreatefromjpeg($source);
$output = "images/certificate".rand(1,200).".jpg";
$white = imagecolorallocate($image,255,255,255);
$black = imagecolorallocate($image,7,94,94);
$font_size = 30;
$rotation = 0;
$origin_x = 250;
$origin_y = 450;
$font = __DIR__ ."/font/Roboto-Italic.ttf";
$text = "Dummy";
$text1 = imagettftext($image,$font_size,$rotation,$origin_x,$origin_y,$black,$font,$text);
     imagejpeg($image,$output,99);
?> <img src="<?php echo $output; ?>"> <a href="<?php echo $output;    ?>" download="<?php echo $output; ?>">Download Certificate</a>
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.