Ajouter du texte sur l'image à l'aide de PIL

93

J'ai une application qui charge une image et lorsque l'utilisateur clique dessus, une zone de texte apparaît pour cette image (en utilisant jquery), où l'utilisateur peut écrire du texte sur l'image. Qui devrait être ajouté sur l'image.

Après avoir fait quelques recherches à ce sujet, j'ai pensé que PIL(Python Imaging Library) pouvait m'aider à le faire. J'ai donc essayé quelques exemples pour voir comment cela fonctionne et j'ai réussi à écrire du texte sur une image. Mais je pense qu'il y a une certaine différence lorsque je l'essaie en utilisant Python Shellet dans un environnement Web. Je veux dire que le texte sur la zone de texte est très gros en px. Comment puis-je obtenir la même taille de texte en utilisant PIL que celui de la zone de texte?

Le texte est Multiline. Comment puis-je le rendre multiligne dans l'image également, en utilisant PIL?

Y a-t-il un meilleur moyen que d'utiliser PIL? Je ne suis pas entièrement sûr, si c'est la meilleure mise en œuvre.

html:

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

c'est l'image en cours d'édition

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

la jquery pour ajouter le textarea. La zone de texte est également position: taille absolue et fixe.

Dois-je le placer dans un formulaire pour pouvoir obtenir les coordonnées de textarea sur l'image? Je veux écrire du texte sur l'image lorsque l'utilisateur clique et l'enregistrer sur l'image.

Apostolos
la source
Pourquoi voulez-vous écrire du texte sur une image en utilisant PIL (et je ne suis pas sûr que PIL y contribue). N'est-il pas suffisant d'afficher le texte en superposition, qui est le plus souvent utilisé dans les curseurs.
lalit
1
J'en ai besoin pour un projet Je veux que l'image soit enregistrée. Pil peut dessiner du texte sur une image en utilisant ImageDraw, je ne sais pas s'il existe un autre moyen.
Apostolos
Ce sera utile, si vous pouvez fournir le code Python que vous utilisez?
lalit
pas encore implémenté dans django. J'ai essayé de voir comment fonctionne PIL dans la console Python interactive. Vous voulez voir si cela fonctionne d'abord, puis transférez-le dans Django.
Apostolos
Quel est le symbole $ dans votre code?
Mugen

Réponses:

171

Je pense que le module ImageFont disponible dans PILdevrait être utile pour résoudre le problème de taille de police du texte. Vérifiez simplement le type et la taille de police qui vous conviennent et utilisez la fonction suivante pour modifier les valeurs de police.

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

Donc, votre code ressemblera à quelque chose de similaire à:

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

Vous devrez peut-être faire un effort supplémentaire pour calculer la taille de la police. Si vous souhaitez le modifier en fonction de la quantité de texte que l'utilisateur a fournie dansTextArea .

Pour ajouter un habillage de texte (chose multiligne), prenez simplement une idée approximative du nombre de caractères pouvant figurer sur une ligne, alors vous pouvez probablement écrire une fonction de pré-traitement pour votre texte, qui trouve essentiellement le caractère qui sera le dernier dans chaque ligne et convertit l'espace blanc avant ce caractère en nouvelle ligne.

lalit
la source
1
C'est ma première pensée. Ai-je donc besoin que mes polices se trouvent dans un dossier spécifique de mon serveur Web pour fonctionner? Je pense que oui. Emballage du texte? Existe-t-il une méthode standard ou dois-je en implémenter une?
Apostolos
Vous pouvez conserver le fichier de police n'importe où sur votre serveur Web. Assurez-vous simplement que le chemin que vous fournissez est correct.
lalit
7
@lalit J'ai essayé votre code sur une machine Windows et j'ai eu une erreur pour la police self.font = core.getfont(file, size, index, encoding) IOError: cannot open resource. Comment puis-je fournir le chemin d'accès au fichier de police?
LWZ
3
@LWZ, Pour exécuter le code ci-dessus, assurez-vous simplement que le fichier de police se trouve dans le répertoire actuel dans lequel vous exécutez le code ci-dessus. Si vous l'utilisez dans votre programme, spécifiez simplement le chemin complet de votre fichier, par exemple «C: \ Windows \ Fonts \ sans-serif.ttf». Une autre chose dont vous devez vous assurer ici est d'accorder les autorisations de lecture appropriées au fichier.
lalit
3
font = ImageFont.truetype ("./ arial.ttf", 30); draw.textsize (msg, font = font);
WeizhongTu
16

Vous pouvez créer un répertoire "fonts" dans une racine de votre projet et y placer votre fichier de polices (sans_serif.ttf). Ensuite, vous pouvez créer quelque chose comme ceci:

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)
svpp
la source
15

Exemple encore plus minimal (dessine "Hello world!" En noir et avec la police par défaut en haut à gauche de l'image):

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

Tout d'abord, vous devez télécharger un type de police ... par exemple: https://www.wfonts.com/font/microsoft-sans-serif .

Après cela, utilisez ce code pour dessiner le texte:

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')
Kumar S
la source
4

Avec Pillow, vous pouvez également dessiner sur une image à l'aide du module ImageDraw. Vous pouvez dessiner des lignes, des points, des ellipses, des rectangles, des arcs, des bitmaps, des accords, des pieslices, des polygones, des formes et du texte.

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

nous créons un objet Image avec la méthode new (). Cela renvoie un objet Image sans image chargée. Nous ajoutons ensuite un rectangle et du texte à l'image avant de l'enregistrer.

Tamil Selvan S
la source
3

Une chose qui n'est pas mentionnée dans d'autres réponses est la vérification de la taille du texte. Il est souvent nécessaire de s'assurer que le texte correspond à l'image (par exemple, raccourcir le texte s'il est surdimensionné) ou de déterminer l'emplacement pour dessiner le texte (par exemple, texte aligné en haut au centre). Pillow / PIL propose deux méthodes pour vérifier la taille du texte, une via ImageFont et une via ImageDraw. Comme indiqué ci-dessous, la police ne gère pas plusieurs lignes, contrairement à 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)) 
lange
la source
-8

Pour ajouter du texte sur un fichier image, copiez / collez simplement le code ci-dessous

<?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>
Ramsevak kumar
la source