Dodaj tekst do obrazu za pomocą PIL


94

Mam aplikację, która ładuje obraz i kiedy użytkownik go kliknie, pojawia się obszar tekstowy dla tego obrazu (za pomocą jquery), w którym użytkownik może napisać tekst na obrazie. Które należy dodać do obrazu.

Po przeprowadzeniu pewnych badań doszedłem do wniosku, że PIL(Python Imaging Library) może mi w tym pomóc. Wypróbowałem więc kilka przykładów, aby zobaczyć, jak to działa i udało mi się napisać tekst na obrazku. Ale myślę, że jest pewna różnica, kiedy próbuję go używać Python Shelli w środowisku internetowym. Chodzi mi o to, że tekst w obszarze tekstowym jest bardzo duży w pikselach. Jak mogę osiągnąć ten sam rozmiar tekstu, używając PIL, jak w obszarze tekstowym?

Tekst jest wielowierszowy. Jak mogę zrobić to również w obrazie wielowierszowym, używając PIL?

Czy jest lepszy sposób niż korzystanie z PIL? Nie jestem do końca pewien, czy to najlepsza realizacja.

html:

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

jego obraz jest edytowany

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

jQuery, aby dodać obszar tekstowy. Również obszar tekstowy to pozycja: bezwzględna i stała wielkość.

Czy powinienem umieścić go w formularzu, aby uzyskać współrzędne obszaru tekstu na obrazie? Chcę napisać tekst na obrazie, gdy użytkownik kliknie i zapisze go na obrazie.


Dlaczego chcesz pisać tekst na obrazie za pomocą PIL (i nie jestem pewien, czy PIL w tym pomaga). Czy nie wystarczy, abyś pokazał tekst w nakładce, która jest najczęściej używana w suwakach.
lalit

1
Potrzebuję go do projektu, w którym chcę zapisać obraz. Pil może narysować tekst na obrazie za pomocą ImageDraw, nie wiem, czy jest inny sposób.
Apostolos

To będzie pomocne, jeśli możesz podać kod Pythona, którego używasz?
lalit

jeszcze nie zaimplementowane w django. Próbowałem zobaczyć, jak PIL działa w interaktywnej konsoli Pythona. Chcesz najpierw sprawdzić, czy to działa, a następnie przenieść je do Django.
Apostolos

Jaki jest symbol $ w Twoim kodzie?
Mugen

Odpowiedzi:


173

Myślę, że moduł ImageFont dostępny w programie PILpowinien być pomocny w rozwiązywaniu problemu rozmiaru czcionki tekstu. Po prostu sprawdź, jaki typ i rozmiar czcionki jest dla Ciebie odpowiedni i użyj następującej funkcji, aby zmienić wartości czcionki.

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

Twój kod będzie więc wyglądał podobnie do:

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')

Obliczenie rozmiaru czcionki może wymagać dodatkowego wysiłku. Jeśli chcesz to zmienić na podstawie ilości tekstu podanego przez użytkownika TextArea.

Aby dodać zawijanie tekstu (rzecz wielowierszowa), po prostu z grubsza wyobraź sobie, ile znaków może znajdować się w jednej linii.Następnie możesz prawdopodobnie napisać funkcję wstępnego przetwarzania dla twojego tekstu, która zasadniczo znajduje znak, który będzie ostatni w każdym wierszu i konwertuje białe znaki przed tym znakiem na nowy wiersz.


1
To moja pierwsza myśl. Czy więc muszę, aby moje czcionki znajdowały się w określonym folderze na moim serwerze internetowym, aby działały? Zawijanie tekstu? Czy istnieje standardowy sposób, czy muszę go wdrożyć?
Apostolos

Możesz przechowywać plik czcionki w dowolnym miejscu na serwerze internetowym. Upewnij się tylko, że podana ścieżka jest poprawna.
lalit

7
@lalit Wypróbowałem Twój kod na komputerze z systemem Windows i otrzymałem błąd dotyczący czcionki self.font = core.getfont(file, size, index, encoding) IOError: cannot open resource. Jak mogę podać ścieżkę do pliku czcionki?
LWZ

3
@LWZ, Aby uruchomić powyższy kod, po prostu upewnij się, że plik czcionki znajduje się w bieżącym katalogu, w którym wykonujesz powyższy kod. Jeśli używasz go w swoim programie, po prostu podaj pełną ścieżkę do pliku, np. „C: \ Windows \ Fonts \ sans-serif.ttf”. Inną rzeczą, którą musisz się tutaj upewnić, jest nadanie odpowiednich uprawnień do odczytu pliku.
lalit

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

16

Możesz utworzyć katalog „fonts” w katalogu głównym swojego projektu i umieścić tam plik czcionek (sans_serif.ttf). Następnie możesz zrobić coś takiego:

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

Jeszcze bardziej minimalny przykład (rysuje napis „Hello world!” Na czarno i domyślną czcionką w lewym górnym rogu obrazu):

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

8

Najpierw musisz pobrać typ czcionki ... na przykład: https://www.wfonts.com/font/microsoft-sans-serif .

Następnie użyj tego kodu, aby narysować tekst:

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

Dzięki Pillow możesz także rysować na obrazie za pomocą modułu ImageDraw. Możesz rysować linie, punkty, elipsy, prostokąty, łuki, bitmapy, akordy, plastry, wielokąty, kształty i tekst.

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')

tworzymy obiekt Image za pomocą metody new (). Zwraca obiekt Image bez załadowanego obrazu. Następnie dodajemy prostokąt i tekst do obrazu przed jego zapisaniem.


4

Jedna rzecz, o której nie wspomniano w innych odpowiedziach, to sprawdzenie rozmiaru tekstu. Często konieczne jest upewnienie się, że tekst pasuje do obrazu (np. Skrócenie tekstu, jeśli jest za duży) lub określenie miejsca, w którym ma zostać narysowany tekst (np. Tekst wyrównany u góry na środku). Pillow / PIL oferuje dwie metody sprawdzania rozmiaru tekstu, jedną przez ImageFont, a drugą przez ImageDraw. Jak pokazano poniżej, czcionka nie obsługuje wielu linii, podczas gdy ImageDraw tak.

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)) 

Dziękuję za podkreślenie tej różnicy. Rzeczywiście szukałem odpowiedniego rozmiaru tekstu w wielu wierszach.
fcole90

-9

Aby dodać tekst do pliku obrazu, po prostu skopiuj / wklej poniższy kod

<?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>
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.