19图片水印添加——一键为数千张员工工牌或产品图加盖 Logo第三阶段PDF 与图片处理16-22场景引入公司有 5000 张产品图片需要加上公司 Logo 水印或 2000 张员工工牌照片需要加盖仅限内部使用的文字水印。用 Photoshop 一张一张处理一个人都要干半天。本节教你用 Python 的 Pillow 库批量为图片添加文字水印或图片水印每秒处理几十张。技术原理使用 PillowPIL Fork库操作图片水印类型实现方式文字水印ImageDraw.text()图片水印LogoImage.paste()或Image.alpha_composite()半透明水印创建透明图层 Image.blend()倾斜水印Image.rotate()原图 → 创建透明图层 → 绘制水印 → 叠加到原图 → 保存环境准备pipinstallPillow完整代码fromPILimportImage,ImageDraw,ImageFont,ImageEnhanceimportosfrompathlibimportPath# 方案 1文字水印 defadd_text_watermark(input_image,output_image,text内部资料,positioncenter,font_size40,color(255,255,255,128),angle0): 为图片添加文字水印 参数: input_image: 输入图片路径 output_image: 输出图片路径 text: 水印文字 position: 位置 center/bottom-right/bottom-left/top-right/top-left font_size: 字体大小 color: 字体颜色 (R, G, B, A) angle: 旋转角度0水平-30左倾斜 # 打开图片imgImage.open(input_image).convert(RGBA)# 创建透明图层txt_layerImage.new(RGBA,img.size,(255,255,255,0))drawImageDraw.Draw(txt_layer)# 获取字体try:fontImageFont.truetype(C:/Windows/Fonts/msyh.ttc,font_size)# 微软雅黑except:fontImageFont.load_default()# 计算文字大小和位置bboxdraw.textbbox((0,0),text,fontfont)text_widthbbox[2]-bbox[0]text_heightbbox[3]-bbox[1]img_width,img_heightimg.size positions{center:((img_width-text_width)//2,(img_height-text_height)//2),bottom-right:(img_width-text_width-20,img_height-text_height-20),bottom-left:(20,img_height-text_height-20),top-right:(img_width-text_width-20,20),top-left:(20,20),}x,ypositions.get(position,positions[center])# 如果需要旋转ifangle!0:# 创建更大的图层以容纳旋转后的文字big_layerImage.new(RGBA,(img_width*2,img_height*2),(255,255,255,0))big_drawImageDraw.Draw(big_layer)big_draw.text((img_width//2,img_height//2),text,fontfont,fillcolor)big_layerbig_layer.rotate(angle,expand0)txt_layerbig_layer.crop((img_width//2,img_height//2,img_width//2img_width,img_height//2img_height))else:draw.text((x,y),text,fontfont,fillcolor)# 叠加resultImage.alpha_composite(img,txt_layer)# 保存转回 RGB 以便保存为 JPEGresultresult.convert(RGB)result.save(output_image,quality95)print(f文字水印:{os.path.basename(input_image)})# 方案 2图片水印Logo defadd_image_watermark(input_image,output_image,logo_path,positionbottom-right,opacity0.5,scale0.15): 为图片添加 Logo 水印 参数: input_image: 输入图片 output_image: 输出图片 logo_path: Logo 图片路径建议 PNG 透明背景 position: 位置 opacity: 透明度0-11完全不透明 scale: Logo 相对原图大小的比例0.1515% imgImage.open(input_image).convert(RGBA)# 打开 LogologoImage.open(logo_path).convert(RGBA)# 缩放 Logonew_logo_size(int(img.width*scale),int(img.height*scale*logo.height/logo.width))logologo.resize(new_logo_size,Image.LANCZOS)# 设置 Logo 透明度ifopacity1:# 调整 alpha 通道r,g,b,alogo.split()aa.point(lambdax:int(x*opacity))logoImage.merge(RGBA,(r,g,b,a))# 计算位置positions{center:((img.width-logo.width)//2,(img.height-logo.height)//2),bottom-right:(img.width-logo.width-20,img.height-logo.height-20),bottom-left:(20,img.height-logo.height-20),top-right:(img.width-logo.width-20,20),top-left:(20,20),}x,ypositions.get(position,positions[bottom-right])# 创建透明图层并粘贴 Logowatermark_layerImage.new(RGBA,img.size,(0,0,0,0))watermark_layer.paste(logo,(x,y))# 叠加resultImage.alpha_composite(img,watermark_layer)resultresult.convert(RGB)result.save(output_image,quality95)print(fLogo水印:{os.path.basename(input_image)})# 方案 3平铺水印全屏重复 defadd_tiled_watermark(input_image,output_image,text内部资料,font_size30,color(255,255,255,50),angle-30,spacing150): 添加平铺水印全屏重复文字 imgImage.open(input_image).convert(RGBA)txt_layerImage.new(RGBA,img.size,(255,255,255,0))drawImageDraw.Draw(txt_layer)try:fontImageFont.truetype(C:/Windows/Fonts/msyh.ttc,font_size)except:fontImageFont.load_default()# 计算文字大小bboxdraw.textbbox((0,0),text,fontfont)text_widthbbox[2]-bbox[0]text_heightbbox[3]-bbox[1]# 平铺y0whileyimg.height:x0row_offset(y//spacing)%2*(spacing//2)# 错行排列whileximg.width:draw.text((xrow_offset,y),text,fontfont,fillcolor)xtext_widthspacing ytext_heightspacing resultImage.alpha_composite(img,txt_layer)resultresult.convert(RGB)result.save(output_image,quality95)print(f平铺水印:{os.path.basename(input_image)})# 批量处理 defbatch_add_watermark(input_dir,output_dir,watermark_func,**kwargs): 批量为文件夹中的所有图片添加水印 input_pathPath(input_dir)output_pathPath(output_dir)output_path.mkdir(parentsTrue,exist_okTrue)image_extensions{.jpg,.jpeg,.png,.bmp,.webp,.tiff}count0forfile_pathininput_path.iterdir():iffile_path.is_file()andfile_path.suffix.lower()inimage_extensions:output_fileoutput_path/file_path.name watermark_func(str(file_path),str(output_file),**kwargs)count1print(f\n批量水印完成:{count}张图片)# 使用示例 if__name____main__:# 单个文件# add_text_watermark(工牌照片.jpg, 工牌_水印.jpg, text内部资料, positioncenter, font_size50)# 批量文字水印batch_add_watermark(input_dir原始工牌照片,output_dir已加水印,watermark_funcadd_text_watermark,text仅限内部使用,positioncenter,font_size40,)# 批量 Logo 水印# batch_add_watermark(# input_dir产品图片,# output_dir已加Logo,# watermark_funcadd_image_watermark,# logo_pathcompany_logo.png,# positionbottom-right,# opacity0.7,# scale0.1# )# 平铺水印防截图# batch_add_watermark(# input_dir机密文档截图,# output_dir平铺水印,# watermark_funcadd_tiled_watermark,# text机密文件,# font_size25,# angle-30,# )常见问题Q1中文水印显示为方框需要指定中文字体路径fontImageFont.truetype(C:/Windows/Fonts/msyh.ttc,font_size)# 微软雅黑# 或fontImageFont.truetype(C:/Windows/Fonts/simsun.ttc,font_size)# 宋体Q2水印太显眼覆盖了图片内容调整color的 alpha 值第四个参数color(255,255,255,50)# alpha50更透明Q3保存 PNG 后水印不见了确保保存时使用RGBA模式并指定 PNG 格式result.save(output_image,PNG)总结水印类型函数适用场景文字水印add_text_watermark()版权声明Logo 水印add_image_watermark()品牌标识平铺水印add_tiled_watermark()防泄漏标记本节掌握了为图片批量添加水印的能力。下一节预告20图片格式转换——Webp/PNG/JPG 批量互转及无损压缩