PIL kullanarak Resme Metin Ekleyin


94

Bir Görüntü yükleyen bir uygulamam var ve kullanıcı onu tıkladığında, bu Görüntü için (kullanarak jquery), kullanıcının Görüntü üzerine biraz metin yazabileceği bir metin alanı beliriyor . Resim üzerine eklenecek olan.

Üzerinde biraz araştırma yaptıktan sonra, PIL(Python Görüntüleme Kitaplığı) 'nın bunu yapmama yardımcı olabileceğini düşündüm . Bu yüzden nasıl çalıştığını görmek için birkaç örnek denedim ve bir resim üzerine metin yazmayı başardım. Ama bunu kullanarak Python Shellve web ortamında denediğimde bazı farklılıklar olduğunu düşünüyorum . Demek istediğim, metin alanındaki metin piksel olarak çok büyük. Metin alanındaki PIL ile aynı boyutta metni nasıl elde edebilirim?

Metin Multiline'dır. Bunu kullanarak görüntüde de nasıl çok satırlı yapabilirim PIL?

PIL kullanmaktan daha iyi bir yol var mı? Bu en iyi uygulama olup olmadığından tam olarak emin değilim.

html:

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

Düzenlenen görüntü

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

textarea eklemek için jquery. Ayrıca metin alanı konumdur: mutlak ve sabit boyut.

Metin alanının koordinatlarını resim üzerinde alabilmek için bir formun içine yerleştirmeli miyim? Kullanıcı tıkladığında resmin üzerine metin yazmak ve resmin üzerine kaydetmek istiyorum.


Neden PIL kullanarak bir Görüntü üzerine metin yazmak istiyorsunuz (ve PIL'in bu konuda yardımcı olup olmadığından emin değilim). En yaygın olarak kaydırıcılarda kullanılan kaplamada metni göstermeniz yeterince iyi değil mi?
lalit

1
Görüntünün kaydedilmesini istediğim bir proje için ihtiyacım var. Pil, ImageDraw kullanarak bir görüntünün üzerine metin çizebilir, başka bir yol olup olmadığını bilmeyin.
Apostolos

Kullanmakta olduğunuz Python kodunu sağlayabilir misiniz?
lalit

henüz django'da uygulanmadı. PIL'in etkileşimli python konsolunda nasıl çalıştığını görmeye çalıştım. Önce çalışıp çalışmadığını görmek ve ardından onu Django'ya aktarmak istiyorum.
Apostolos

Kodunuzdaki $ sembolü nedir?
Mugen

Yanıtlar:


173

Bence mevcut ImageFont modülü PILmetin yazı tipi boyutu problemini çözmede yardımcı olmalı. Sizin için hangi yazı tipi ve boyutunun uygun olduğunu kontrol edin ve yazı tipi değerlerini değiştirmek için aşağıdaki işlevi kullanın.

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

Yani kodunuz şuna benzer görünecektir:

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

Yazı tipi boyutunu hesaplamak için fazladan çaba göstermeniz gerekebilir. Kullanıcının sağladığı metin miktarına göre değiştirmek istemeniz durumunda TextArea.

Metin sarma (Çok satırlı şey) eklemek için, bir satırda kaç karakterin gelebileceğine dair kabaca bir fikir edin, O zaman muhtemelen Metniniz için bir ön işleme işlevi yazabilirsiniz, Temel olarak her satırda son olacak karakteri bulur ve bu karakterden önceki beyaz boşluğu yeni satıra dönüştürür.


1
Bu benim ilk düşüncem. Çalışmak için yazı tiplerimin web sunucumdaki belirli bir klasörde olmasına ihtiyacım var mı? Metin sarma? Standart bir yol var mı yoksa uygulamalı mıyım?
Apostolos

Yazı tipi dosyasını web sunucunuzun herhangi bir yerinde tutabilirsiniz. Sağladığınız yolun doğru olduğundan emin olun.
lalit

7
@lalit Kodunuzu bir Windows makinesinde denedim ve yazı tipi için bir hata aldım self.font = core.getfont(file, size, index, encoding) IOError: cannot open resource. Yazı tipi dosyasının yolunu nasıl sağlayabilirim?
LWZ

3
@LWZ, Yukarıdaki kodu çalıştırmak için, yazı tipi dosyasının yukarıdaki kodu çalıştırdığınız geçerli dizinde olduğundan emin olun. Programınızda kullanıyorsanız, dosyanızın tam yolunu belirtmeniz yeterlidir, örn. 'C: \ Windows \ Fonts \ sans-serif.ttf'. Burada emin olmanız gereken diğer şey, dosyaya uygun okuma izinleri vermektir.
lalit

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

16

Projenizin kök dizinine bir "yazı tipi" dizini oluşturabilir ve yazı tipi (sans_serif.ttf) dosyanızı oraya koyabilirsiniz. O zaman bunun gibi bir şey yapabilirsiniz:

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

Daha da minimal bir örnek (siyah renkte ve resmin sol üst köşesindeki varsayılan yazı tipiyle "Merhaba dünya!" Çizer):

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

8

Öncelikle, bir yazı tipi türü indirmelisiniz ... örneğin: https://www.wfonts.com/font/microsoft-sans-serif .

Bundan sonra, metni çizmek için bu kodu kullanın:

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 ile, ImageDraw modülünü kullanarak da bir görüntü üzerinde çizim yapabilirsiniz. Çizgiler, noktalar, elipsler, dikdörtgenler, yaylar, bitmapler, akorlar, pieslices, çokgenler, şekiller ve metinler çizebilirsiniz.

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 () yöntemiyle bir Image nesnesi oluşturuyoruz. Bu, yüklenmiş görüntü içermeyen bir Görüntü nesnesi döndürür. Daha sonra, kaydetmeden önce resme bir dikdörtgen ve bir miktar metin ekliyoruz.


4

Diğer cevaplarda belirtilmeyen bir şey, metin boyutunu kontrol etmektir. Genellikle metnin resme uyduğundan emin olmak (örneğin, büyükse metni kısaltmak) veya metni çizmek için yeri belirlemek (örneğin, hizalanmış metin üst ortaya) gerekir. Pillow / PIL, metin boyutunu kontrol etmek için biri ImageFont ve diğeri ImageDraw yoluyla olmak üzere iki yöntem sunar. Aşağıda gösterildiği gibi, yazı tipi çoklu satırları işlemezken, ImageDraw yapar.

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

Bu farkı vurguladığınız için teşekkürler. Gerçekten çok satırlı doğru metin boyutunu arıyordum.
fcole90

-9

Bir resim dosyasına metin eklemek için aşağıdaki kodu kopyalayıp yapıştırmanız yeterlidir

<?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>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.