I am building a thumbnail creation program and I need to turn a string into an image of that string so that it can be pasted into the thumbnail. I am using the PIL Image module for working with my images.
For example, if I am given a string of "#53" I want to be able to create a PNG of that string so that I can put it in the bottom right corner of the thumbnail. My current plan for implementing this is to have a PNG of every single character in a folder, and then loop through the string and stitch together the images of the single characters until the whole string is stitched together. However, this seems a little sloppy, and it would also be hard to change fonts and it would also be difficult to even find such a library of PNGs for every single letter. Any suggestions?
PIL does what you want directly. From the docs, http://effbot.org/imagingbook/imagefont.htm
import ImageFont, ImageDraw
draw = ImageDraw.Draw(image)
# use a bitmap font
font = ImageFont.load("arial.pil")
draw.text((10, 10), "hello", font=font)
# use a truetype font
font = ImageFont.truetype("arial.ttf", 15)
draw.text((10, 25), "world", font=font)
Related
Is There any way to use google custom fonts in Tkinter Application.
I have google Font zip file from google font and I want to use that in my tkinter application.
I've came to the same problem, unfortunately it doesn't seem to be possible to use custom fonts in traditional way anyways.
But I came to a workaround by making a image with that text onto it.
def create_text_image(self, text, color_rgba_code_tuple):
fnt = Enums.ImageFont.truetype(Enums.FONT_DEFAULT, Enums.FONT_SIZE)
text_width, text_height = fnt.getsize(text)
img = Enums.Image.new('RGBA', (text_width,text_height))
d = Enums.ImageDraw.Draw(img)
d.text((0,0), text, font=fnt,fill=color_rgba_code_tuple)
img.save(Enums.FONT_TEMPORARY_IMAGE_PATH)
return Enums.PhotoImage(file=Enums.FONT_TEMPORARY_IMAGE_PATH)
Imports
from PIL import Image, ImageDraw, ImageFont, ImageTk
Explanation
You need to pass in your text and rgba tuple into the function; so, something like (255,255,255,255) for white text.
And then simply add that image that the function returns to a list, and use it in wherever place you want (like Canvas for example).
Hope this is clear.
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()
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
I have a given image. I want to create a black strip as an overlay on this image, with text written on the said strip. Here's a visual example of what I mean.
I'm using Python PIL to accomplish this (in a Django project), and here's what I've written so far:
from PIL import Image, ImageFont, ImageDraw
img_width, img_height = img.size #getting the base image's size
if img.mode != 'RGB':
img = img.convert("RGB")
strip = Image.new('RGB', (img_width, 20)) #creating the black strip
draw = ImageDraw.Draw(strip)
font = ImageFont.truetype("/usr/share/fonts/truetype/freefont/FreeSansBold.ttf", 16)
draw.text((img_width/2,10),"foo bar",(255,255,255),font=font) #drawing text on the black strip
offset = (img_width/2,img_height/2)
img.paste(strip,offset) #pasting black strip on the base image
# and from here on, I save the image, create thumbnails, etc.
This isn't working at all. As in, the image appears without any text or black strip, like it originally was.
Note that if I directly try to write on the image (sans the black strip), it works perfectly. Moreover, image processing itself is working perfectly too (i.e. in cases where I don't write anything on the image).
Can anyone help me point out the problem? Is something wrong with the position (or offset)? Am I pasting it wrong? Is RGB conversion to blame? Or is it something else entirely? An illustrative example would be great. Btw performance matters too; I'm trying to do this as costlessly as I can.
In case it matters, here's what I do with the image file later:
from django.core.files.uploadedfile import InMemoryUploadedFile
img.thumbnail((300, 300))
thumbnailString = StringIO.StringIO()
img.save(thumbnailString, 'JPEG', optimize=True)
newFile = InMemoryUploadedFile(thumbnailString, None, 'temp.jpg','image/jpeg', thumbnailString.len, None)
# and then the image file is saved in a database object, to be served later
The problem is with offset. The docs Image.paste says:
If a 2-tuple is used instead, it’s treated as the upper left corner.
So with (img_width/2, img_height/2), you're pasting the strip with it's top-left corner in the middle of the big image. Here it is pasting "foo bar" onto your example picture:
If you change it to offset = (0, img_height/2), it pastes it halfway down but from the left. Here's "foo bar" pasted into the correct location:
The strip could do with being a bit taller (the height could be calculated from the text at the given font size), and the text could be centred, but I expect those things have already been answered elsewhere on Stack Overflow or in the Pillow docs.
I am very new to opencv. Here I am trying to create an Image which will be a shape made of a string with 0's and 1's (The function random_shape generates that string). So the string is to be typed on top of a white background . Here I am able to create a White Background Image but unable to add text in front of it. It just creates a blank image. It also gives a segmentation fault if I give it different coordinates.
Any Help is Appreciated .
font = cv2.FONT_HERSHEY_SIMPLEX
blank_image = np.zeros((100,100,3), np.uint8)
cv2.putText(blank_image,random_shape(100,100),(0,0), cv2.FONT_HERSHEY_SIMPLEX, 2,(0,255,0))
blank_image[:,0:1*100] = (255,255,255)
image=cv2.cv.fromarray(blank_image)
cv2.cv.SaveImage('pic.jpg', image)
Update : I have changed my code to
blank_image = np.zeros((512,512,3), np.uint8)
blank_image[:,0:512] = (255,255,255)
cv2.putText(blank_image,random_shape(100,100)[0:100],(0,0), cv2.FONT_HERSHEY_\
SIMPLEX, 0.1,(0,0,0),cv2.CV_AA)
image=cv2.cv.fromarray(blank_image)
cv2.cv.SaveImage('pic.jpg', image)
It seems to be something garbled (its some sort of text with a line) instead of numbers. The size of the text also appears large.Any Help !!
First, you can just save an image using cv2.imwrite("filename.jpg", blank_image).
The docstring for cv2.putText(...) is:
putText(img, text, org, fontFace, fontScale, color[, thickness[, lineType[, bottomLeftOrigin]]]) -> None
The second argument of cv2.putText, "text", is a string. Chances are, random_shape in your code does not store "valid" characters. So you are passing values to cv2.putText that cannot be "translated" to proper characters that can be displayed.
Why don't you debug by manually specifying a string in place of the values obtained from random_shape? That way, you can test whether the problem is with your code or with the libraries that OpenCV uses print characters or write to the image file etc.
It seems I needed to remove cv2.CV_AA and also in case of multiple lines of output there needs to be sufficient vertical spacing.
blank_image = np.zeros((512,512,3), np.uint8)
blank_image[:,0:512] = (255,255,255)
cv2.putText(blank_image,random_shape(100,100)[0:100],(10,10), cv2.FONT_HERSHEY_\
SIMPLEX, 0.2,(0,0,0))
image=cv2.cv.fromarray(blank_image)
cv2.cv.SaveImage('pic.jpg', image)
I managed to create something like this adding the above code in a function. Need to work a bit more on it.