水印:将旋转文本粘贴到空图像

2024-03-29 11:59:00 发布

您现在位置:Python中文网/ 问答频道 /正文

我想旋转和过去的旋转图像一样,在附加的图像。 我的结果未居中,文本不在图像中。 图像大小为794x1096 你能帮我吗

这是我的代码:

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

Example


Tags: path代码textname图像文本imginput
1条回答
网友
1楼 · 发布于 2024-03-29 11:59:00

创建普通水平水印更容易,因为它需要更少的工作

您必须创建与原始图像大小相同但背景透明的新空图像RGBA。接下来,您可以在不同的位置以不同的透明度绘制此新图像文本。最后,您必须使用Image.alpha_composite(original_image, text_image)以期望的透明度在图像上放置文本

要将文本放在中间,必须使用

x = original_image_width/2 - text_width/2
y = original_image_height/2 - text_height/2

enter image description here

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

现在,您可以将文本放在不同的位置,并且可以使用for-loop进行此操作

enter image description here

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

放置旋转的图像需要更多的工作,因为首先必须使用文本生成图像,旋转图像,然后使用paste()将其放置在透明图像上,最后使用alpha_composite()将透明图像放置在原始图像上

enter image description here

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

此版本是通用的,因为您还可以使用此方法放置水平文本-您只需跳过rotate()。如果需要,还可以添加一些重缩放或其他修改

但是,当文本图像太大,并且一个包含文本的矩形与另一个包含文本的矩形重叠时,可能会出现问题,因为paste()会删除以前的内容。然后它需要更复杂的版本,使用alpha_composite()而不是paste()


顺便说一句:维基百科Lenna的原始图像:

enter image description here


编辑:

以前的版本有重叠文本图像的问题

enter image description here

新版本将每个文本单独合并,解决了这个问题

enter image description here

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

编辑:

我将代码更改为使用行中的行数来计算位置

对于2个单词,我将宽度分成3部分。在这个版本中,我使用线条来显示这些部分。文本的中心位于交叉线的位置

enter image description here

这种计算有一个缺点——它会在图像周围产生更大的边距

这将需要不同的计算来减少它。它必须得到图像宽度,减去2*文本宽度,然后将其分成3部分。然后第一个元素的位置需要1*part_size + 0*text_with,第二个元素的位置需要2*part_size + 1*text_with,第n个元素的位置需要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')

具有更好计算边距的代码

enter image description here

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

相关问题 更多 >