Python text with alpha channel background - python

I'm working with Python 2.7.3 and PIL/Pillow and want to create text (with opacity) on an alpha_channel background saved as png. Here is my code which doesn't do exactly, what I was hoping:
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
from PIL import ImageEnhance
width=854
height=480
opacity=0.8
text='copyright'
filename = 'result.png'
black = (0,0,0)
white = (255,255,255)
font = ImageFont.truetype('verdana.ttf',15)
wm = Image.new('RGBA',(width,height),white)
im = Image.new('L',(width,height),0)
draw = ImageDraw.Draw(wm)
w,h = draw.textsize(text, font)
draw.text(((width-w)/2,(height-h)/2),text,white,font)
en = ImageEnhance.Brightness(wm)
#en.putalpha(mask)
mask = en.enhance(1-opacity)
im.paste(wm,(25,25),mask)
im.save(filename)
Result:
The following code is what I'm looking for, but the background fully transparent/alpha_channel:
import PIL
from PIL import ImageFont
from PIL import Image
from PIL import ImageDraw
width = 854
height = 480
black = (0,0,0)
text = "copyright"
white = (255,255,255)
font = ImageFont.truetype("Arial.ttf",40)
img = Image.new("RGBA", (width,height),white)
draw = ImageDraw.Draw(img)
w, h = draw.textsize(text, font)
draw.text(((width-w)/2,(height-h)/2),text,black,font=font)
draw = ImageDraw.Draw(img)
#img.putalpha
img.save("result.png")
#img.show
Result:

The problem is that wm has the same color as the text, so you won't see anything if you draw the text onto it. Change the color of wm to transparent, like I did below (and remove the commas after initializing of width, height and opacity):
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
from PIL import ImageEnhance
width=854
height=480
opacity=0.8
text='copyright'
filename = 'result.png'
black = (0,0,0)
white = (255,255,255)
transparent = (0,0,0,0)
font = ImageFont.truetype('verdana.ttf',15)
wm = Image.new('RGBA',(width,height),transparent)
im = Image.new('RGBA',(width,height),transparent) # Change this line too.
draw = ImageDraw.Draw(wm)
w,h = draw.textsize(text, font)
draw.text(((width-w)/2,(height-h)/2),text,white,font)
en = ImageEnhance.Brightness(wm)
#en.putalpha(mask)
mask = en.enhance(1-opacity)
im.paste(wm,(25,25),mask)
im.save(filename)

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

Python PIL - add text BEFORE image (on top of image NOT on the image)

How can I add text on top of an image (i.e NOT INSIDE the image)?
from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw
img = Image.open("SAMPLE-IN.png")
draw = ImageDraw.Draw(img)
# font = ImageFont.truetype(<font-file>, <font-size>)
font = ImageFont.truetype("FONTS/arial.ttf", 36)
# draw.text((x, y),"Sample Text",(r,g,b))
draw.text((0,0),"Sample Text",(0,255,255),font=font)
img.save('sample-out.jpg')
You should create an image that is bigger than the original one, paste the first one and the text onto it, like this:
from PIL import Image, ImageFont, ImageDraw, ImageOps
img = Image.open("SAMPLE-IN.png")
img = ImageOps.expand(img, border=10, fill=(255,255,255))
draw = ImageDraw.Draw(img)
font = ImageFont.truetype("FONTS/arial.ttf", 36)
draw.text((0,0),"Sample Text",(0,255,255),font=font)
img.save('sample-out.jpg')

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

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