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.