首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >水印:将旋转文本粘贴到空图像

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

Stack Overflow用户
提问于 2020-07-15 08:15:56
回答 1查看 820关注 0票数 0

我想旋转和通过旋转的图像,就像在图像所附。我的结果不是居中的,文本不在图像中。图像大小是794x1096,你能帮我吗?

这是我的密码:

代码语言:javascript
运行
复制
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')

示例

EN

回答 1

Stack Overflow用户

发布于 2020-07-16 08:29:42

它更容易创建正常的水平水印,因为它需要较少的工作。

您必须创建新的空图像RGBA,其大小与原始图像相同,但具有透明的背景(..., ..., ..., 0)。接下来,您可以以不同的透明度和不同的位置使用这个新的图像文本。最后,您必须使用Image.alpha_composite(original_image, text_image)将文本放在图像上,并具有预期的透明度。

要将文本放在中间,必须使用以下方法计算其上/左角

代码语言:javascript
运行
复制
x = original_image_width/2 - text_width/2
y = original_image_height/2 - text_height/2

代码语言:javascript
运行
复制
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进行此操作。

代码语言:javascript
运行
复制
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()将透明图像放到原始图像上。

代码语言:javascript
运行
复制
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()版本。

BTW:维基百科的原始兰娜图片:

编辑:

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

新版本将每一个文本分开组合,解决了这个问题。

代码语言:javascript
运行
复制
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*text_width,然后将它分成3部分。第一个元素的位置需要1*part_size + 0*text_with,对于第二个2*part_size + 1*text_with,对于n个n*part_size + (n-1)*text_with

代码语言:javascript
运行
复制
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')

具有更好计算边距的代码

代码语言:javascript
运行
复制
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')
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62910445

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档