Rendering Emoji with PIL - python

I am trying to make images out of tweets, however some of them contain Emojis. I am using PIL to render my images and the Symbola font.
The text is in unicode utf-8 encoding and the Symbola font does include the emojis. Here is an abridged version of the code:
from PIL import Image, ImageFont, ImageDraw
text = u"\U0001f300" #CYCLONE emoji
image = Image.new("RGBA", (100,100), (255,255,255))
font = ImageFont.truetype("Symbola.ttf", 60, encoding='unic')
draw = ImageDraw.Draw(image)
draw.text((0,0), text, (0,0,0), font=font)
image.save("Test.png")
image.show()
This just renders and image with two rectangles instead of the emoji
Would appreciate any help or ideas.
Thanks!
EDIT: As falsetru pointed out, this code does run in Ubuntu, however it doesn't run on Windows or on Mac. Any ideas?

If the symbol CYCLONE u"\U0001f300" (I download a Symbola.tff from web) then is a very simple to use with PIL:
from PIL import Image, ImageDraw, ImageFont, ImageFilter
#configuration
font_size=36
width=500
height=100
back_ground_color=(255,255,255)
font_size=36
font_color=(0,0,0)
unicode_text =u"\U0001f300"
im = Image.new ( "RGB", (width,height), back_ground_color )
draw = ImageDraw.Draw ( im )
unicode_font = ImageFont.truetype("Symbola.ttf", font_size)
draw.text ( (10,10), unicode_text, font=unicode_font, fill=font_color )
im.show()
Take a look at this

There was a bug in Pillow, see #1774 or #3777. This should now be fixed in version 6.1 of Pillow with PR#3780, but only for Python 3.x.

If you are looking to write symbols with your original font, you can do this by merging your font with Symbola.ttf or any emojis font. You can merge the two fonts using fontforge (https://fontforge.org/).
start fontforge, open up your main font,
Click menu: element->merge fonts and choose your emoji font (Symbola.ttf).
answer no for any popup dialog.
optionally change your new font's name: element->font info.
finally go to file->generate fonts when done and save it as ttf (TrueType).
Now, you can use your generated font to draw text with emojis!

Related

Specific unicode character not displayed properly in python image

I am trying to create an image with some unicode characters but some of them aren't being displayed properly. You can see in this sample image:
The character in question I am trying to print is \u2BEA, which is a half star image. Unfortunately the output just shows me the generic missing character icon.
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
output_image = Image.new('RGB', (200,100), (0,0,0))
text = '\u2605\u2605\u2605\u2BEA\u2606'
font = ImageFont.truetype("C:\\Windows\\Fonts\\yugothb.ttc", 18)
draw = ImageDraw.Draw(output_image)
draw.text((10, 10), text, (255,255,255), font=font)
output_image.show()
Note: you may need to adjust the font location for your computer
In my sample code I'm using the Yu Gothic Bold font and not getting the correct output. I have tried using other fonts such as Arial and Calibri, which produced even worse results.
My thought process is that the character isn't part of of the font but I have yet to find a font that supports it.
Does anyone know of a free font that I can use that will display this character?
Unicode 'u2BEA' defined as "STAR WITH LEFT HALF BLACK", but not defined in any font file on my platform.
Maybe you can download and use following font files,
BabelStone Han
https://www.babelstone.co.uk/Fonts/Download/BabelStoneHan.ttf
Symbola
https://dn-works.com/wp-content/uploads/2020/UFAS-Fonts/Symbola.zip
Unifont
https://unifoundry.com/pub/unifont/unifont-13.0.06/font-builds/unifont-13.0.06.ttf
Note: Last one with large font than '\u2605' and '\u2606'.
I didn't find any font that includes \u2BEA or \u2BE8 (ref: https://www.unicode.org/charts/nameslist/n_2B00.html#2BEA), but the following icons by Font Awesome might meet your needs: Star Icon (Solid) Stat Half Alt Icon (Solid) Star Icon (Regular)
In Font Awesome, f005 refers to the 'star' icon, and f5c0 refers to the 'star-half-alt' icon.
So, you can download Font Awesome Free for Desktop at https://use.fontawesome.com/releases/v5.15.3/fontawesome-free-5.15.3-desktop.zip, then draw solid \uF005\uF005\uF005\uF5C0 with 'Font Awesome 5 Free-Solid-900.otf' and a single hollow star \uF005 with 'Font Awesome 5 Free-Regular-400.otf'.
The following works properly:
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
output_image = Image.new('RGB', (200,100), (0,0,0))
solid = ImageFont.truetype('fontawesome-free-5.15.3-desktop/otfs/Font Awesome 5 Free-Solid-900.otf', 18)
regular = ImageFont.truetype('fontawesome-free-5.15.3-desktop/otfs/Font Awesome 5 Free-Regular-400.otf', 18)
draw = ImageDraw.Draw(output_image)
draw.text((10, 10), '\uF005' * 3 + '\uF5C0', (255,255,255), font=solid)
draw.text((90, 10), '\uF005', (255,255,255), font=regular)
output_image.show()

How to add words on a picture and bold one of them using Pillow in Python?

I add text on the image using PIL library in Python. How can I bold one word in a sentence? Let's say I want to write in the picture: "This is an example sentence".
Currently, you can't bold, underline, italicize etc. certain parts of a sentence. You can use multiple separate .text() commands and change their x-y coordinates to make it look like one sentence. To bold text, you can use a bolded text font in a font family, and use that font for a .text() command. In the example below, I used the Arial and the Arial Bold font. I am on a windows machine, so the file paths will be different on Linux or Mac.
Code:
#import statements
import PIL
import PIL.Image as Image
import PIL.ImageDraw as ImageDraw
import PIL.ImageFont as ImageFont
#save fonts
font_fname = '/fonts/Arial/arial.ttf'
font_fname_bold = '/fonts/Arial/arialbd.ttf'
font_size = 25
#regular font
font = ImageFont.truetype(font_fname, font_size)
#bolded font
font_bold = ImageFont.truetype(font_fname_bold, font_size)
#Open test image. Make sure it is in the same working directory!
with Image.open("test.jpg") as img:
#Create object to draw on
draw = ImageDraw.Draw(img)
#Add text
draw.text(xy=(10,10),text="Gardens have ",font=font)
draw.text(xy=(175,10),text="many",font=font_bold)
draw.text(xy=(240,10),text=" plants and flowers",font=font)
#Display new image
img.show()
Test image:
https://i.stack.imgur.com/zU75J.jpg

How to create an exact match of an image using PIL in python?

I'm seeing a tiny difference in image I created using PIL of python than the actual one and because of this difference my sikuli script fails to click since its an image based automation tool.
The approach is to create an image & click it, based on the object name to be clicked on screen during run-time.
Code to create image :
import PIL
from PIL import ImageFont
from PIL import Image
from PIL import ImageDraw
from PIL import ImageEnhance
font = ImageFont.truetype("C:\\SikuliWS\\R419\\Fonts\\calibri.ttf",11)
img=Image.new("RGBA", (0,0)) #To create an empty white background
draw = ImageDraw.Draw(img) #draw an image with 0,0
textsze = draw.textsize(imageString) #Create a text to capture w/h
print textsze
img=Image.new("RGBA", (textsze[0],textsze[1]+3),(255,255,255)) #create a white background as per the w/h of text passed
draw = ImageDraw.Draw(img)
draw.text((0, 0),imageString,(13,13,13),font=font)
img.save("imageString.png", format='PNG',quality=100)
Output:
Actual image created:
Expected image:
Notice the tiny difference between characters ID and the space between characters because of which sikuli fails to click.
How do I create an exact match of image using python 2.7? Please help.

Alternatives to PIL/Pillow for overlaying an image with text

Do any Python alternatives exist for overlaying an image with text? I tried with PIL/Pillow, but the output is really grainy and artifacted.
Here is my code:
from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw
img = Image.open("image.jpg")
draw = ImageDraw.Draw(img)
font = ImageFont.truetype("Comic Sans MS.ttf", 24)
draw.text((150, 20),"Sample Text",(170,14,179), font=font)
img.save('sample-out123.jpg')
and the output:
You can see artifacting around the text as well as a light purple glow.
This is a known problem with JPEG images.
Try changing the image quality:
img.save('sample-out123.jpg', quality=95)
Or, save as a PNG.
img.save('sample-out123.png')

Python, PIL; Text to Image and fonts

I have an issue with writing text to an image under Python and PIL -
I'm able to write text to a png file, though not bold text. Could anyone provide an example of how to achieve this?
I thought the easiest solution may be was use a bold-variant of a text, but I'm unable to see anything in the Windows/font folder that supplies this - does this mean font types have a 'bold attribute' that is T/F?:
Code I'm using:
import PIL
from PIL import ImageFont
from PIL import Image
from PIL import ImageDraw
# font = ImageFont.truetype("Arial-Bold.ttf",14)
font = ImageFont.truetype("Arial.ttf",14)
img=Image.new("RGBA", (500,250),(255,255,255))
draw = ImageDraw.Draw(img)
draw.text((0, 0),"This is a test",(0,0,0),font=font)
draw = ImageDraw.Draw(img)
img.save("a_test.png")
A simple way to do it:
font = ImageFont.load_default().font
Also you can do a google search for 'verdana.ttf' and download it put it in the same directory as the python file:
Then add it like this:
font = ImageFont.truetype("Verdana.ttf",14)
You aren't looking at actual font files in the control panel (explorer magically turns into the font viewer control panel when in the Windows/fonts folder as well), they are grouped by family for your convenience. Double click the family to see the fonts in the family:
Then right-click and choose properties to find the file name:

Categories