How to find the correct Image size - python

I am trying to convert Text to image in Python
This is the code:
As long as the text is in single line,
For example "Text to write on img 1234567890"
It is fine
But if the text contains "\n" then the image clips and size calculations become incorrect
"Text to write on \n img 1234567890"
Please help
import numpy as np
import time
import text_to_image
from PIL import Image, ImageDraw, ImageFont
import os
from win32api import GetSystemMetrics
def text_on_img(filename='01.png', text="Text to write on \n img 1234567890", size=200, color=(0,0,0), bg='white'):
"Draw a text on an Image, saves it, show it"
fnt = ImageFont.truetype('arial.ttf', size)
# create image
image = Image.new(mode = "RGB", size = (int(size/2)*len(text),size+50), color = bg)
draw = ImageDraw.Draw(image)
# draw text
draw.text((10,10), text, font=fnt, fill=(0,0,0))
# save file
image.save(filename)
# show file
os.system(filename)
text_on_img()

I fixed it perfectly. Please test it.
import os
from PIL import Image, ImageDraw, ImageFont
def text_on_img(filename='01.png', text="Text to write on \n img 1234567890", size=200, color=(0, 0, 0), bg='white'):
"Draw a text on an Image, saves it, show it"
fnt = ImageFont.truetype('arial.ttf', size)
# create image
width = max([int(size/2) * len(line) for line in text.split('\n')])
height = (size + 50) * len(text.split('\n'))
image = Image.new(mode="RGB", size=(width, height), color=bg)
draw = ImageDraw.Draw(image)
# draw text
draw.text((10, 10), text, font=fnt, fill=(0, 0, 0))
# save file
image.save(filename)
# show file
os.system(filename)
text_on_img()
The result:

One approach is multiplying size with the number of occurrences of \n.
n = text.count('\n') + 2
# create image
image = Image.new(mode = "RGB", size = (int(size/2)*len(text),size*n), color = bg)
Result:
If you remove \n from the text, the result will be:
Other examples:

Related

Python PIL - How to put text on a video

I am writing a program that puts captions on the screen and I am using PIL because it has high-quality text that is way better than the default moviepy text. I currently can put the text on a black screen, I tried using a fully transparent image as a sort of hack but that didn't work. So if anyone knows how to put PIL text on an image, or up the quality of the default moviepy text, let me know, please. Here is my basic code to put white text on a black background:
import numpy as np
from moviepy.editor import *
from PIL import Image, ImageFont, ImageDraw
SIZE = (1280, 720)
DURATION = 2
FPS = 1
TEXT = "I am having a hard time"
FONT_SIZE = 100
TEXT_COLOR_HEX = "#ffffff"
FONT = "Amiri-Bold"
def create_PIL():
img = Image.new("RGB", size=SIZE)
#draw = ImageDraw.Draw(img)
draw = ImageDraw.Draw(img)
font = ImageFont.truetype(f"../Fonts/UniNeue-Trial-Bold.ttf", size=FONT_SIZE)
draw.text((100, 100), TEXT, font=font, fill=TEXT_COLOR_HEX)
img = np.array(img)
return VideoClip(lambda t: img, duration=DURATION).set_fps(FPS)
final = concatenate_videoclips(
[create_PIL()]
)
final.write_videofile('./test.mp4')
I am trying to put this text onto a video, and I need to have custom start and duration times but all this does it put it on a black screen, which is what I expected but not what I want.

creating a filled in rectangle/shape around text using PIL

I have a pre-existing image that I have added a border to and text, I would like to place a rectangle around the text area to make it similar to a gold embedded plate on a picture or painting.
I am using draw.text to write and position the text, but can't figure out how to do the shape border & fill around the text parameters.
import os
from PIL import Image, ImageOps, ImageDraw, ImageFont
import glob
## SINGLE IMAGE
img = Image.open('Art/AB-2020 (2).jpg')
add_grey_border = ImageOps.expand(img,border=50,fill='grey')
add_black_border = ImageOps.expand(add_grey_border,border=300,fill='black')
add_black_border.save('Art/imaged-with-border.png')
## Function to add Title to image
def add_title(img_src, title):
img = Image.open(img_src, 'r')
draw = ImageDraw.Draw(img)
w, h = img.size
font = ImageFont.truetype("arial.ttf", 100)
text_w, text_h = draw.textsize(title, font)
draw.text(((w - text_w) / 2, (h-100) - text_h), title, (255,255,255),
font=font, stroke_width=2, stroke_fill='#eeda19')
img.save(img_src)
return img_src
add_title('Art/imaged-with-border.png', 'test')
what I have so far:
painting with text
If I can get the nameplate correct I will remove the stroke_fill.
I want it to look like this:
What I am trying to achieve

By Using python pil, I want to make image centered with text from url and download. How to do it?

I input a text at url, and want to get downloaded image that the text is centered.
for example,
when I input,
http://127.0.0.1:8000/app/hello, then an image is downloaded.
That image centers the text 'hello'
def homework(request, name):
text = name
img = Image.new('RGB',(256,256),(0,0,0))
draw = ImageDraw.Draw(img)
font = ImageFont.load_default().font
draw.text((128,128), text, font = font, fill="black")
with open(img, 'rb') as f:
response = HttpResponse(f, content_type='image/jpeg')
response['Content-Disposition'] = 'attachment; filename="textimage"'
return response
By using python pil.
How to do it?
#install PIL (Pillow) via Pip
from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw
#position of Text
x = 50
y = 50
#font color as tuple
color = (255, 255, 255)
#download the image to the local system and open it
img = Image.open("1.jpg")
#draw image and prepare font
draw = ImageDraw.Draw(img)
font = ImageFont.truetype('arial.ttf', size=30)
#draw text on image
draw.text((x, y),"Sample Text", color,font=font)
#save the new image, that contains the text
img.save('sample-out.jpg')

Python image library - font positioning

EDIT: added complete working example
I have the following program:
from PIL import Image, ImageDraw, ImageFont
FULL_SIZE = 50
filename = 'font_test.png'
font="/usr/share/fonts/truetype/msttcorefonts/arial.ttf"
text="5"
image = Image.new("RGBA", (FULL_SIZE, FULL_SIZE), color="grey")
draw = ImageDraw.Draw(image)
font = ImageFont.truetype(font, 40)
font_width, font_height = font.getsize(text)
draw.rectangle(((0, 0), (font_width, font_height)), fill="black")
draw.text((0, 0), text, font=font, fill="red")
image.save(filename, "PNG")
This generates the following image:
It seems that when writing the text PIL library adds some margin at the top. This margin depends on the font I use.
How can I take this into account when trying to position the text (I want it to be in the middle of a rectangle)?
(Using Python 2.7.6 with Pillow 2.3.0 on Ubuntu 14.04)
I don't understand why, but subtracting font.getoffset(text)[1] from the y co-ordinate fixes it on my computer.
from PIL import Image, ImageDraw, ImageFont
FULL_SIZE = 100
filename = 'font_posn_test.png'
fontname = '/usr/share/fonts/truetype/msttcorefonts/arial.ttf'
textsize = 40
text = "5"
image = Image.new("RGBA", (FULL_SIZE, FULL_SIZE))
draw = ImageDraw.Draw(image)
font = ImageFont.truetype(fontname, textsize)
print font.getoffset(text)
print font.font.getsize(text)
font_width, font_height = font.getsize(text)
font_y_offset = font.getoffset(text)[1] # <<<< MAGIC!
draw.rectangle(((0, 0), (font_width, font_height)), fill="black")
draw.text((0, 0 - font_y_offset), text, font=font, fill="red")
image.save(filename, "PNG")

How to convert a string to an image?

I started to learn python a week ago and want to write a small program that converts a email to a image (.png) so that it can be shared on forums without risking to get lots of spam mails.
It seems like the python standard library doesn't contain a module that can do that but I've found out that there's a PIL module for it (PIL.ImageDraw).
My problem is that I can't seem to get it working.
So basically my questions are:
How to draw a text onto a image.
How to create a blank (white) image
Is there a way to do this without actually creating a file so that I can show it in a GUI before saving it?
Current Code:
import Image
import ImageDraw
import ImageFont
def getSize(txt, font):
testImg = Image.new('RGB', (1, 1))
testDraw = ImageDraw.Draw(testImg)
return testDraw.textsize(txt, font)
if __name__ == '__main__':
fontname = "Arial.ttf"
fontsize = 11
text = "example#gmail.com"
colorText = "black"
colorOutline = "red"
colorBackground = "white"
font = ImageFont.truetype(fontname, fontsize)
width, height = getSize(text, font)
img = Image.new('RGB', (width+4, height+4), colorBackground)
d = ImageDraw.Draw(img)
d.text((2, height/2), text, fill=colorText, font=font)
d.rectangle((0, 0, width+3, height+3), outline=colorOutline)
img.save("D:/image.png")
use ImageDraw.text - but it doesn't do any formating, it just prints string at the given location
img = Image.new('RGB', (200, 100))
d = ImageDraw.Draw(img)
d.text((20, 20), 'Hello', fill=(255, 0, 0))
to find out the text size:
text_width, text_height = d.textsize('Hello')
When creating image, add an aditional argument with the required color (white):
img = Image.new('RGB', (200, 100), (255, 255, 255))
until you save the image with Image.save method, there would be no file. Then it's only a matter of a proper transformation to put it into your GUI's format for display. This can be done by encoding the image into an in-memory image file:
import cStringIO
s = cStringIO.StringIO()
img.save(s, 'png')
in_memory_file = s.getvalue()
or if you use python3:
import io
s = io.BytesIO()
img.save(s, 'png')
in_memory_file = s.getvalue()
this can be then send to GUI. Or you can send direct raw bitmap data:
raw_img_data = img.tostring()
The first 3 lines are not complete, when I'm not wrong. The correct code would be:
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont

Categories