Reputation: 31
I want to rotate and past the rotated image just like in the image attached. My result is not centered and the text is out of the image. The image size is 794x1096 May you help me please?
This is my code:
x = input('Insert Name Here ')
y = input('Insert full name')
img = Image.open("Path/watermark_example.png")
draw = ImageDraw.Draw(img)
font = ImageFont.truetype('calibri.ttf', 55)
draw.text((30, 300),x,(128, 128, 128, 255), font=font)
draw.text((500, 500),x,(128, 128, 128, 255),font=font)
img1 = img.rotate(15, expand = True, fillcolor = 'white')
img.putalpha(128)
img.paste(img1)
img.show()
img.save(f'Path/watermark_example{y}.png')
Upvotes: 1
Views: 1562
Reputation: 143057
It is easier to create normal horizontal watermark because it needs less work.
You have to create new empty image RGBA
with the same size as original image but with transparent background (..., ..., ..., 0)
. Next you can draw on this new image text with different transparency and in different place. Finally you have to use Image.alpha_composite(original_image, text_image)
to put text on image with expected transparency.
To put text in center you have to calculate its top/left corner using
x = original_image_width/2 - text_width/2
y = original_image_height/2 - text_height/2
from PIL import Image, ImageDraw, ImageFont
#name = input('Name: ')
name = 'example'
# --- original image ---
#original_image_size = (794, 1096)
#original_image = Image.new('RGBA', image_size, 'white')
original_image = Image.open('lenna.png').convert("RGBA")
original_image_size = original_image.size
# --- watermarks image ---
# image with the same size and transparent color (..., ..., ..., 0)
watermarks_image = Image.new('RGBA', original_image_size, (255,255,255,0))
watermarks_draw = ImageDraw.Draw(watermarks_image)
font = ImageFont.truetype('arial.ttf', 55)
# calculate text size in pixels (width, height)
text_size = font.getsize(name)
# calculate top/left corner for centered text
#x = (image_size[0] - text_size[0])//2
#y = (image_size[1] - text_size[1])//2
x = original_image_size[0]//2 - text_size[0]//2
y = original_image_size[1]//2 - text_size[1]//2
# draw text
watermarks_draw.text((x, y), name, (255, 255, 255, 192), font=font)
# --- put watermarks image on original image ---
combined_image = Image.alpha_composite(original_image, watermarks_image)
# --- result ---
combined_image.show()
combined_image.save(f'lenna_1_{name}.png')
Now you can put text in different places and you can use for
-loop for this
from PIL import Image, ImageDraw, ImageFont
#name = input('Name: ')
name = 'example'
# --- original image ---
#original_image_size = (794, 1096)
#original_image = Image.new('RGBA', image_size, 'white')
original_image = Image.open('lenna.png').convert("RGBA")
original_image_size = original_image.size
# --- watermarks image ---
# image with the same size and transparent color (..., ..., ..., 0)
watermarks_image = Image.new('RGBA', original_image_size, (255,255,255,0))
watermarks_draw = ImageDraw.Draw(watermarks_image)
font = ImageFont.truetype('arial.ttf', 15)
# calculate text size in pixels (width, height)
text_size = font.getsize(name)
# calculate top/left corner for centered text
parts = 8
offset_x = original_image_size[0]//parts
offset_y = original_image_size[1]//parts
start_x = original_image_size[0]//parts - text_size[0]//2
start_y = original_image_size[1]//parts - text_size[1]//2
for a in range(0, parts, 2):
for b in range(0, parts, 2):
x = start_x + a*offset_x
y = start_y + b*offset_y
watermarks_draw.text((x, y), name, (255, 255, 255, 240), font=font)
# --- put watermarks image on original image ---
combined_image = Image.alpha_composite(original_image, watermarks_image)
# --- result ---
combined_image.show()
combined_image.save(f'lenna_2_{name}.png')
It needs more work to put rotated image because first you have to generate image with text, rotate it and then put it on transparent image using paste()
, and finally you put transparent image on original image using alpha_composite()
.
from PIL import Image, ImageDraw, ImageFont
#name = input('Name: ')
name = 'example'
# --- original image ---
#original_image_size = (794, 1096)
#original_image = Image.new('RGBA', image_size, 'white')
original_image = Image.open('lenna.png').convert("RGBA")
original_image_size = original_image.size
# --- text image ---
font = ImageFont.truetype('arial.ttf', 55)
# calculate text size in pixels (width, height)
text_size = font.getsize(name)
# create image for text
text_image = Image.new('RGBA', text_size, (255,255,255,0))
text_draw = ImageDraw.Draw(text_image)
# draw text on image
text_draw.text((0, 0), name, (255, 255, 255, 129), font=font)
# rotate text image and fill with transparent color
rotated_text_image = text_image.rotate(45, expand=True, fillcolor=(0,0,0,0))
rotated_text_image_size = rotated_text_image.size
#rotated_text_image.show()
# --- watermarks image ---
# image with the same size and transparent color (..., ..., ..., 0)
watermarks_image = Image.new('RGBA', original_image_size, (255,255,255,0))
# calculate top/left corner for centered text
x = original_image_size[0]//2 - rotated_text_image_size[0]//2
y = original_image_size[1]//2 - rotated_text_image_size[1]//2
# put text on watermarks image
watermarks_image.paste(rotated_text_image, (x, y))
# --- put watermarks image on original image ---
combined_image = Image.alpha_composite(original_image, watermarks_image)
# --- result ---
combined_image.show()
combined_image.save(f'lenna_3_{name}.png')
This version is universal because you can use this method also to put horizontal text - you have to only skip rotate()
. You can also add some rescaling or other modifiacation to if you need.
But it may have problem when text images are too big and one rectangle with text overlap onother rectangel with text because paste()
remove previous content. And then it would need more complex version with alpha_composite()
instead of paste()
BTW: Original image of Lenna from Wikipedia:
EDIT:
Previous version has problem with overlapping text images
New version combines every text separatelly and it resolves this problem.
from PIL import Image, ImageDraw, ImageFont
#name = input('Name: ')
name = 'example'
# --- original image ---
#original_image_size = (794, 1096)
#original_image = Image.new('RGBA', image_size, 'white')
original_image = Image.open('lenna.png').convert("RGBA")
original_image_size = original_image.size
# --- text image ---
font = ImageFont.truetype('arial.ttf', 55)
# calculate text size in pixels (width, height)
text_size = font.getsize(name)
# create image for text
text_image = Image.new('RGBA', text_size, (255,255,255,0))
text_draw = ImageDraw.Draw(text_image)
# draw text on image
text_draw.text((0, 0), name, (255, 255, 255, 129), font=font)
# rotate text image and fill with transparent color
rotated_text_image = text_image.rotate(45, expand=True, fillcolor=(0,0,0,0))
rotated_text_image_size = rotated_text_image.size
#rotated_text_image.show()
# --- watermarks image ---
combined_image = original_image
# calculate top/left corner for centered text
parts = 8
offset_x = original_image_size[0]//parts
offset_y = original_image_size[1]//parts
start_x = original_image_size[0]//parts - rotated_text_image_size[0]//2
start_y = original_image_size[1]//parts - rotated_text_image_size[1]//2
for a in range(0, parts, 2):
for b in range(0, parts, 2):
x = start_x + a*offset_x
y = start_y + b*offset_y
# image with the same size and transparent color (..., ..., ..., 0)
watermarks_image = Image.new('RGBA', original_image_size, (255,255,255,0))
# put text in expected place on watermarks image
watermarks_image.paste(rotated_text_image, (x, y))
# put watermarks image on original image
combined_image = Image.alpha_composite(combined_image, watermarks_image)
#combined_image.show()
# --- result ---
combined_image.show()
combined_image.save(f'lenna_4b_{name}.png')
EDIT:
I change code to use nubmer of rows in row to calculate position.
For 2 words I split width on 3 parts. In this version I use lines to show these parts. Center of text is in place of crossing lines.
This calculation has one disadvanget - it creates bigger margin around image.
It would different calculations to reduce it. It would have to get image width and substract 2*text_width and then divide it on 3 parts. And then position for first element would need 1*part_size + 0*text_with
, for second 2*part_size + 1*text_with
, for n-th n*part_size + (n-1)*text_with
from PIL import Image, ImageDraw, ImageFont
#name = input('Name: ')
name = 'example'
# --- original image ---
#original_image_size = (794, 1096)
#original_image = Image.new('RGBA', image_size, 'white')
original_image = Image.open('lenna.png').convert("RGBA")
original_image_size = original_image.size
# --- watermarks image ---
# image with the same size and transparent color (..., ..., ..., 0)
watermarks_image = Image.new('RGBA', original_image_size, (255,255,255,0))
watermarks_draw = ImageDraw.Draw(watermarks_image)
font = ImageFont.truetype('arial.ttf', 35)
# calculate text size in pixels (width, height)
text_size = font.getsize(name)
# calculate
words_in_row = 2
words_in_col = 2
parts_x = words_in_row + 1 # 3
size_x = original_image_size[0]//parts_x
offset_x = text_size[0]//2 # half of text's width
parts_y = words_in_col + 1 # 3
size_y = original_image_size[1]//parts_y
offset_y = text_size[1]//2 # half of text's height
for a in range(1, parts_x, 1):
line_x = a*size_x
line_heigth = original_image.size[1]
watermarks_draw.line((line_x, 0, line_x, line_heigth))
for b in range(1, parts_y, 1):
line_y = b*size_y
line_width = original_image.size[0]
watermarks_draw.line((0, line_y, line_width, line_y))
x = a*size_x - offset_x
y = b*size_y - offset_y
watermarks_draw.text((x, y), name, (255, 255, 255, 240), font=font)
# --- put watermarks image on original image ---
combined_image = Image.alpha_composite(original_image, watermarks_image)
# --- result ---
combined_image.show()
combined_image.save(f'lenna_2_{name}.png')
Code with better calculate margins
from PIL import Image, ImageDraw, ImageFont
#name = input('Name: ')
name = 'example'
# --- original image ---
#original_image_size = (794, 1096)
#original_image = Image.new('RGBA', image_size, 'white')
original_image = Image.open('lenna.png').convert("RGBA")
original_image_size = original_image.size
# --- watermarks image ---
# image with the same size and transparent color (..., ..., ..., 0)
watermarks_image = Image.new('RGBA', original_image_size, (255,255,255,0))
watermarks_draw = ImageDraw.Draw(watermarks_image)
font = ImageFont.truetype('arial.ttf', 35)
# calculate text size in pixels (width, height)
text_size = font.getsize(name)
text_width, text_height = text_size
# calculate
words_in_row = 2
words_in_col = 4
parts_x = words_in_row + 1 # 3
margin_x = (original_image_size[0] - words_in_row*text_width)//parts_x
offset_x = text_width//2 # half of text's width
parts_y = words_in_col + 1 # 3
margin_y = (original_image_size[1] - words_in_col*text_height)//parts_y
offset_y = text_size[1]//2 # half of text's height
for a in range(0, parts_x, 1):
line_height = original_image.size[1]
line_x = (a+1) * margin_x + a * text_width
watermarks_draw.line((line_x, 0, line_x, line_height))
line_x += text_width
watermarks_draw.line((line_x, 0, line_x, line_height))
for b in range(0, parts_y, 1):
line_width = original_image.size[0]
line_y = (b+1) * margin_y + b * text_height
watermarks_draw.line((0, line_y, line_width, line_y))
line_y += text_height
watermarks_draw.line((0, line_y, line_width, line_y))
x = (a+1) * margin_x + a * text_width
y = (b+1) * margin_y + b * text_height
watermarks_draw.text((x, y), name, (255, 255, 255, 240), font=font)
# --- put watermarks image on original image ---
combined_image = Image.alpha_composite(original_image, watermarks_image)
# --- result ---
combined_image.show()
combined_image.save(f'lenna_7_{name}.png')
Upvotes: 7