岳阳网站建设设计,如何制作个人网页链接,有没有大人和小孩做的网站,手游平台怎么搭建文章目录 1. 简介2. PIL库概述3. PIL库中涉及的类4. 实现原理5. 实现过程5.1 原始图片5.2 导入相关模块5.3 初始化数据5.4 水印字体设置5.5 打开原始图片并创建存储对象5.6 计算图片和水印的大小5.7 选择性设置水印文字5.8 绘制文字并设置透明度5.9 遍历获取图片文件并调用绘制… 文章目录 1. 简介2. PIL库概述3. PIL库中涉及的类4. 实现原理5. 实现过程5.1 原始图片5.2 导入相关模块5.3 初始化数据5.4 水印字体设置5.5 打开原始图片并创建存储对象5.6 计算图片和水印的大小5.7 选择性设置水印文字5.8 绘制文字并设置透明度5.9 遍历获取图片文件并调用绘制方法 6. 完整源码7. 效果展示8. 改进与建议8.1 参数输入方式优化8.2 异常处理改进8.3 代码结构优化8.4 日志记录8.5 扩展功能 9. 优化图片格式检查10. 增加用户交互性11. 多线程处理12. 其他优化建议 1. 简介
在日常图像处理中为图片添加水印是一项常见任务。有多种方法和工具可供选择而今天我们将专注于使用Python语言结合PIL库批量添加水印。
需要注意的是所选用的图片格式不应为JPG或JPEG因为这两种格式的图片不支持透明度设置。
2. PIL库概述 先前的文章已经详细介绍过PIL库这里不再赘述。 PIL是Python的图像处理库支持多种文件格式。PIL提供强大的图像和图形处理功能包括缩放、裁剪、叠加以及添加线条、文字等操作。安装PIL库可使用以下命令
pip install Pillow3. PIL库中涉及的类
模块或类说明image模块用于图像处理ImageDraw2D图像对象ImageFont字体存储ImageEnhance图像增强
4. 实现原理 本文的主要目标是批量为某个文件夹下的图片添加水印实现原理如下 设置水印内容使用Image对象的open()方法打开原始图片使用Image对象的new()方法创建存储水印图片的对象使用ImageDraw.Draw对象的text()方法绘制水印文字使用ImageEnhance中Brightness的enhance()方法设置水印透明度。
5. 实现过程
5.1 原始图片
设定原始图片的存储目录例如
F:\python_study\image\image015.2 导入相关模块
导入所需的PIL模块或类
from PIL imort Image, ImageDraw, ImageFont, ImageEnhance
import os5.3 初始化数据
通过用户手动输入相关信息如图片存储路径、水印文字、水印位置、水印透明度等
class WatermarkText():def __init__(self):super(WatermarkText, self).__init__()self.image_path input(图片路径)self.watermark_text input(水印文字)self.position_flag int(input(水印位置1左上角2左下角3右上角4右下角5居中))self.opacity float(input(水印透明度0—1之间的1位小数))5.4 水印字体设置
选择系统字体库中的字体
self.font ImageFont.truetype(cambriab.ttf, size35)5.5 打开原始图片并创建存储对象
打开原始图片并转换为RGBA
image Image.open(img).convert(RGBA)创建绘制对象
new_img Image.new(RGBA, image.size, (255, 255, 255, 0))
image_draw ImageDraw.Draw(new_img)5.6 计算图片和水印的大小
计算图片大小
w, h image.size计算文字大小
w1 self.font.getsize(self.watermark_text)[0]
h1 self.font.getsize(self.watermark_text)[1]5.7 选择性设置水印文字
通过if语句实现
if self.position_flag 1: # 左上角location (0, 0)
elif self.position_flag 2: # 左下角location (0, h - h1)
elif self.position_flag 3: # 右上角location (w - w1, 0)
elif self.position_flag 4: # 右下角location (w - w1, h - h1)
elif self.position_flag 5: # 居中location (h/2, h/2)5.8 绘制文字并设置透明度
绘制文字
image_draw.text(location, self.watermark_text, fontself.font, fillblue)设置透明度
transparent new_img.split()[3]
transparent ImageEnhance.Brightness(transparent).enhance(self.opacity)
new_img.putalpha(transparent)Image.alpha_composite(image, new_img).save(img)5.9 遍历获取图片文件并调用绘制方法
watermark_text WatermarkText()
try:file_list os.listdir(watermark_text.image_path)for i in range(0, len(file_list)):filepath os.path.join(watermark_text.image_path, file_list[i])if os.path.isfile(filepath):filetype os.path.splitext(filepath)[1]if filetype .png:watermark_text.add_text_watermark(filepath)else:print(图片格式有误请使用png格式图片)print(批量添加水印完成)
except:print(输入的文件路径有误请检查~~)6. 完整源码 from PIL importImage, ImageDraw, ImageFont, ImageEnhance
import osclass WatermarkText():def __init__(self):super(WatermarkText, self).__init__()self.image_path input(图片路径)self.watermark_text input(水印文字)self.position_flag int(input(水印位置1左上角2左下角3右上角4右下角5居中))self.opacity float(input(水印透明度0—1之间的1位小数))# 设置字体self.font ImageFont.truetype(cambriab.ttf, size35)# 文字水印def add_text_watermark(self, img):global locationimage Image.open(img).convert(RGBA) new_img Image.new(RGBA, image.size, (255, 255, 255, 0)) image_draw ImageDraw.Draw(new_img) w, h image.size # 图片大小w1 self.font.getsize(self.watermark_text)[0] # 字体宽度h1 self.font.getsize(self.watermark_text)[1] # 字体高度# 设置水印文字位置if self.position_flag 1: # 左上角location (0, 0)elif self.position_flag 2: # 左下角location (0, h - h1)elif self.position_flag 3: # 右上角location (w - w1, 0)elif self.position_flag 4: # 右下角location (w - w1, h - h1)elif self.position_flag 5: # 居中location (h/2, h/2)# 绘制文字image_draw.text(location, self.watermark_text, fontself.font, fillblue)# 设置透明度transparent new_img.split()[3]transparent ImageEnhance.Brightness(transparent).enhance(self.opacity)new_img.putalpha(transparent)Image.alpha_composite(image, new_img).save(img)if __name__ __main__:watermark_text WatermarkText()try:file_list os.listdir(watermark_text.image_path) for i in range(0, len(file_list)): filepath os.path.join(watermark_text.image_path, file_list[i])if os.path.isfile(filepath): filetype os.path.splitext(filepath)[1] if filetype .png: watermark_text.add_text_watermark(filepath) else:print(图片格式有误请使用png格式图片)print(批量添加水印完成)except:print(输入的文件路径有误请检查~~)7. 效果展示
运行过程
D:\Python37\python.exe F:/python_study/python_project/watermark_text.py
图片路径F:\python_study\image\image01
水印文字
水印位置1左上角2左下角3右上角4右下角5居中1
水印透明度0—1之间的1位小数0.5
F:/python_study/python_project/watermark_text.py:32: DeprecationWarning: getsize is deprecated and will be removed in Pillow 10 (2023-07-01). Use getbbox or getlength instead.w1 self.font.getsize(self.watermark_text)[0] # 获取字体宽度
F:/python_study/python_project/watermark_text.py:33: DeprecationWarning: getsize is deprecated and will be removed in Pillow 10 (2023-07-01). Use getbbox or getlength instead.h1 self.font.getsize(self.watermark_text)[1] # 获取字体高度
批量添加水印完成8. 改进与建议
8.1 参数输入方式优化
在初始化数据的部分我们可以考虑通过命令行参数或配置文件的方式输入相关信息以提高用户体验。例如使用argparse库来解析命令行参数。
import argparseclass WatermarkText():def __init__(self):parser argparse.ArgumentParser(descriptionAdd watermark to images.)parser.add_argument(--image_path, typestr, helpPath to the image directory.)parser.add_argument(--watermark_text, typestr, helpText for watermark.)parser.add_argument(--position_flag, typeint, helpPosition flag for watermark (1: top-left, 2: bottom-left, 3: top-right, 4: bottom-right, 5: center).)parser.add_argument(--opacity, typefloat, helpOpacity for watermark (0-1 with 1 decimal place).)args parser.parse_args()self.image_path args.image_path or input(Image path: )self.watermark_text args.watermark_text or input(Watermark text: )self.position_flag args.position_flag or int(input(Watermark position (1: top-left, 2: bottom-left, 3: top-right, 4: bottom-right, 5: center): ))self.opacity args.opacity or float(input(Watermark opacity (0-1 with 1 decimal place): ))8.2 异常处理改进
在处理异常的部分我们可以更具体地捕获异常类型并提供更友好的提示信息。
try:# existing code...
except FileNotFoundError:print(Error: The specified image directory does not exist.)
except PermissionError:print(Error: Permission denied to access the specified image directory.)
except Exception as e:print(fAn unexpected error occurred: {e})8.3 代码结构优化
可以考虑将一些功能模块化提高代码的可读性和维护性。例如将文字水印的添加功能独立成一个方法。
class WatermarkText():# existing code...def add_text_watermark(self, img):# existing code...8.4 日志记录
考虑在程序中添加日志记录记录关键步骤和出错信息以便于排查问题。
import logginglogging.basicConfig(levellogging.INFO)class WatermarkText():# existing code...def add_text_watermark(self, img):try:# existing code...logging.info(fSuccessfully added watermark to {img})except Exception as e:logging.error(fError adding watermark to {img}: {e})8.5 扩展功能
在程序中可以考虑添加更多功能比如支持不同的水印颜色、字体大小等选项以使程序更加灵活。
这些改进和建议将有助于提高程序的稳定性、易用性和可维护性。
当然我们将继续改进和完善你的代码。在这一部分我们会考虑一些进一步的优化和改进。
9. 优化图片格式检查
在处理图片文件时可以优化检查图片格式的方式。使用os.path.splitext得到的文件扩展名可能包含大写字母为了确保匹配可以将文件扩展名转换为小写。
if filetype.lower() .png:watermark_text.add_text_watermark(filepath)
else:print(Error: Image format is not supported. Please use PNG format.)10. 增加用户交互性
可以考虑在程序中增加更多用户交互性比如在成功添加水印后询问用户是否继续添加水印。
while True:try:# existing code...print(Watermark added successfully.)another input(Do you want to add watermark to another image? (yes/no): ).lower()if another ! yes:breakexcept Exception as e:logging.error(fError: {e})这样用户可以选择是否继续添加水印提高程序的交互性。
11. 多线程处理
如果你需要处理大量图片可以考虑使用多线程来加速处理过程。这可以通过concurrent.futures模块实现。
from concurrent.futures import ThreadPoolExecutor# existing code...if __name__ __main__:watermark_text WatermarkText()try:file_list os.listdir(watermark_text.image_path) with ThreadPoolExecutor() as executor:executor.map(watermark_text.add_text_watermark, [os.path.join(watermark_text.image_path, file) for file in file_list])print(Batch watermarking completed.)except Exception as e:logging.error(fError: {e})这将允许同时处理多个图片提高处理速度。
12. 其他优化建议
考虑支持更多图片格式而不仅限于PNG。你可以使用Pillow库中的Image.register_open()方法注册其他格式的图片打开器。如果水印文字较长可以考虑自动调整文字大小以适应图片。