运行流程
- 读取剪切板最新一条内容
- 如果不是图片则退出
- 判断图片色彩偏白还是偏黑
- 生成对应颜色的水印
- 生成带水印图片
- 将添加水印后的图片写入剪切板
完整代码
import math
from io import BytesIO
import win32clipboard
from PIL import Image, ImageFont, ImageDraw, ImageEnhance, ImageChops
from PIL import ImageGrab
def write_img2clipboard(img):
"""将指定图片写入到剪切板中"""
win32clipboard.OpenClipboard()
try:
win32clipboard.EmptyClipboard()
out = BytesIO()
img.save(out, "BMP")
data = out.getvalue()[14:]
win32clipboard.SetClipboardData(win32clipboard.CF_DIB, data)
finally:
win32clipboard.CloseClipboard()
def read_clipboard_img():
img = ImageGrab.grabclipboard()
if img is None:
return
if isinstance(img, list):
img = Image.open(img[0])
if img.mode != 'RGBA':
img = img.convert('RGBA')
return img
def crop_image(im):
'''裁剪图片边缘空白'''
bg = Image.new(mode='RGBA', size=im.size)
bbox = ImageChops.difference(im, bg).getbbox()
if bbox:
return im.crop(bbox)
return im
def set_opacity(im, opacity):
'''设置水印透明度'''
assert 0 <= opacity <= 1
alpha = im.split()[3]
alpha = ImageEnhance.Brightness(alpha).enhance(opacity)
im.putalpha(alpha)
return im
def set_mark_color(image):
'''设置水印颜色'''
pixels = list(image.getdata())
num_pixels = len(pixels)
total = 0
for pixel in pixels:
total += pixel[0] + pixel[1] + pixel[2] + pixel[3]
avg_pixel_value = total / (num_pixels * 4)
if avg_pixel_value > 128:
return '#5b5b66'
else:
return "#f6f6f6"
def get_mark_img(text, color="#8B8B1B", size=30, opacity=0.15):
'''生成水印'''
width = len(text) * size
mark = Image.new(mode='RGBA', size=(width, size + 20))
ImageDraw.Draw(im=mark) \
.text(xy=(0, 0),
text=text,
fill=color,
font=ImageFont.truetype('msyhbd.ttc', size=size))
mark = crop_image(mark)
set_opacity(mark, opacity)
return mark
def img_add_mark(im, text, size=15, opacity=0.15, angle=45):
try:
color = set_mark_color(im)
mark = get_mark_img(text, color, size, opacity)
w, h = im.size
except:
return
space = round(w / 10)
c = int(math.sqrt(w ** 2 + h ** 2))
mark2 = Image.new(mode='RGBA', size=(c, c))
y, idx = 0, 0
mark_w, mark_h = mark.size
while y < c:
x = -int((mark_w + space) * 0.5 * idx)
idx = (idx + 1) % 2
while x < c:
mark2.paste(mark, (x, y))
x = x + mark_w + space
y = y + mark_h + space
mark2 = mark2.rotate(angle)
im.paste(mark2, (int((w - c) / 2), int((h - c) / 2)),
mask=mark2.split()[3])
write_img2clipboard(im)
if __name__ == "__main__":
img = read_clipboard_img()
img_add_mark(img, '途杰工作室 Tool4j')