演示图
说明
照片边框添加 | Python | 免费无广告
🔅理论上Mac及Windos都可运行,只需要python环境即可~~~
🔅目前提供了两种样式,白色边框以及透明边框:P2是原图,P3是白色边框的效果,P4是透明边框效果。
🔅使用方法如下:
(一)将需要添加边框的照片放入到【images_input】文件夹中,一次可添加多张,如P5所示。
(二)在该文件夹下运行python代码:①python3 WorT.py W可为图片添加白色边框。②python3 WorT.py T可为图片添加透明边框。
(三)从images_output中获取结果!
🔅声明:给照片添加边框的创意早已存在,本人在收集整理前人代码(酷安、CSDN、GPT)的基础上优化生成更加【方便、好用】的新代码,并且【免费】分享给大家,后期有空也会继续迭代升级~~~~
代码
代码如下,绑定的资源文件请自行下载:
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import exifread
import os
from fractions import Fraction
from PIL import Image, ImageDraw, ImageFont, ImageOps, ImageFilter
import shutil
import argparse
# 遍历文件夹处理
def watermark(srcPath, distPath,color):
# 遍历文件夹
for filename in os.listdir(srcPath):
# 目录验证
if not os.path.exists(distPath):
os.makedirs(distPath)
# 拼接完整的文件或文件夹路径
srcFile = os.path.join(srcPath, filename)
distFile = os.path.join(distPath, filename)
# 如果是文件 就调用exinfo
if os.path.isfile(srcFile):
if is_image(srcFile):
# 执行压缩操作
imageprocess(srcFile, distFile, color)
else:
print(" 文件不是图片,跳过!")
# 如果是文件夹 就继续递归
elif os.path.isdir(srcFile):
watermark(srcFile, distPath)
# 文件是否为图片判断
def is_image(srcFile):
return srcFile.lower().endswith(('.png', '.jpg', '.jpeg', '.tif', '.tiff'))
# 开始处理图片
def imageprocess(srcFile,distFile,color):
if color == "T": #透明的
imageprocess2(srcFile,distFile)
else:
try:
tags = exifread.process_file(open(srcFile, 'rb')) # 获取照片的exif信息并更新需要写入的文字
except:
print("出错跳过")
else:
品牌 = ""
机型 = ""
镜头 = ""
logo_img = "logo/SONY.png"
快门 = ""
ISO = ""
光圈 = ""
焦距 = ""
if 'EXIF ISOSpeedRatings' in tags.keys():
ISO = "ISO" + str(tags['EXIF ISOSpeedRatings'])
if 'Image Make' in tags.keys():
品牌 = str(tags['Image Make'])
if 'Image Model' in tags.keys():
机型 = str(tags['Image Make']) + " " + str(tags['Image Model'])
if 'EXIF FNumber' in tags.keys():
fnum = float(Fraction(str(tags['EXIF FNumber'])))
光圈 = "f/" + str(fnum)
if 'EXIF ExposureTime' in tags.keys():
speed = Fraction(str(tags['EXIF ExposureTime']))
快门 = str(speed)
if 'EXIF FocalLengthIn35mmFilm' in tags.keys():
焦距 = str(tags['EXIF FocalLengthIn35mmFilm']) + "mm"
else:
焦距 = str(tags['EXIF FocalLength']) + "mm"
if 'EXIF LensModel' in tags.keys():
镜头 = str(tags['EXIF LensModel'])
else:
镜头 = ""
# 选择logo
if 品牌 == "SONY":
logo_img = "logo/SONY.png"
if 品牌 == "Panasonic":
logo_img = "logo/Lumix.png"
if 'Exif.Panasonic.LensType' in tags.keys():
镜头 = str(tags['EXIF LensModel'])
else:
镜头 = ""
if 品牌 == "vivo":
logo_img = "logo/ZEISS.png"
机型 = str(tags['Image Model'])
extime = Fraction(str(tags['EXIF ExposureTime'])).limit_denominator(300)
快门 = str(extime)
if 品牌 == "Canon":
logo_img = "logo/Canon.png"
机型 = str(tags['Image Model'])
if 品牌 == "NIKON CORPORATION":
logo_img = "logo/NIKON-2.png"
机型 = str(tags['Image Model'])
if 品牌 == "Xiaomi":
logo_img = "logo/leica.png"
机型 = str(tags['Image Model'])
if 机型 == "M2006J10C":
length = float(Fraction(str(tags['EXIF FocalLength'])))
焦距 = str(length) + "mm"
extime = Fraction(str(tags['EXIF ExposureTime'])).limit_denominator(300)
快门 = str(extime)
if 品牌 == "Google":
logo_img = "logo/Google.png"
extime = Fraction(str(tags['EXIF ExposureTime'])).limit_denominator(300)
快门 = str(extime)
if 品牌 == "PENTAX":
logo_img = "logo/PENTAX.png"
机型 = str(tags['Image Model'])
if 品牌 == "RICOH":
logo_img = "logo/PENTAX.png"
if 品牌 == "FUJIFILM":
logo_img = "logo/FUJIFILM.png"
if 品牌 == "GoPro":
logo_img = "logo/GoPro.png"
if 品牌 == "Olympus":
logo_img = "logo/Olympus.png"
if 品牌 == "PhaseOne":
logo_img = "logo/PhaseOne.png"
if 品牌 == "Hasselblad":
logo_img = "logo/Hasselblad.png"
if 品牌 == "HUAWEI":
logo_img = "logo/HUAWEI.png"
焦段 = 焦距 + " " + 光圈 + " " + 快门 + " " + ISO
# 打开原始照片
待处理照片 = Image.open(srcFile)
待处理照片 = ImageOps.exif_transpose(待处理照片)
待处理照片宽, 待处理照片高 = 待处理照片.size
# ========可设定参数
背景边框宽度 = 600
背景边框高度 = 500
高斯数值 = 15
#=========样式优化
水印横向偏置 = 待处理照片宽 / 8
# # 创建模糊背景
# 模糊背景 = 待处理照片.copy()
# 模糊背景 = 模糊背景.filter(ImageFilter.GaussianBlur(高斯数值))
# 模糊背景 = 模糊背景.resize((待处理照片宽 + 背景边框宽度, 待处理照片高 + 背景边框高度), Image.Resampling.LANCZOS)
# 创建一个比原始照片大一些的新图像,添加模糊背景边框
背景图 = Image.new('RGB', (待处理照片宽 + 背景边框宽度, 待处理照片高 + 背景边框高度), (255, 255, 255))
# 背景图.paste(模糊背景, (0, 0))
# 计算图片粘贴位置使其居中
paste_x = (背景图.width - 待处理照片宽) // 2
paste_y = (背景图.height - 待处理照片高 - 170) // 2 # 留出空间放水印
背景图.paste(待处理照片, (paste_x, paste_y))
# 在模糊背景上绘制水印
draw = ImageDraw.Draw(背景图)
# 绘制三段文字
font1 = ImageFont.truetype("font/Siemens Sans Bold.ttf", 84)
font2 = ImageFont.truetype("font/msyh.ttc", 60)
font3 = ImageFont.truetype("font/msyh.ttc", 78)
draw.text((paste_x + 水印横向偏置, paste_y + 待处理照片高 + 54), 机型, fill=(0, 0, 0, 255), font=font1) #164
draw.text((paste_x + 水印横向偏置, paste_y + 待处理照片高 + 154), 镜头, fill=(122, 122, 122, 255), font=font2)#164
draw.text((paste_x + 待处理照片宽 - 水印横向偏置 - 1000, paste_y + 待处理照片高 + 99), 焦段, fill=(0, 0, 0, 255), font=font3)#2708 焦段、光圈、iso信息;1000是这行字的宽度
# 绘制分隔线
分割线偏置 = 待处理照片宽 - 水印横向偏置 - 1000 - 54 #54是上面这段字和分隔线的距离
draw.line(((paste_x + 分割线偏置, paste_y + 待处理照片高 + 64), (paste_x + 分割线偏置, paste_y + 待处理照片高 + 236)), (197, 197, 197, 255), width=6)#2644 比上面小54
# 通过图片绘制logo
图标偏置 = int(分割线偏置 - 54 - 185)
if 机型 != "":
logo = Image.open(logo_img)
logo图片宽, logo图片高 = logo.size
if logo图片宽 > logo图片高:
背景图.paste(logo, (paste_x + 图标偏置, paste_y + 待处理照片高 + 62)) #2300
else:
背景图.paste(logo, (paste_x + 图标偏置, paste_y + 待处理照片高 + 62))
背景图.save(distFile, quality=100, exif=待处理照片.info['exif'])
print(srcFile, "已处理完成")
def imageprocess2(srcFile, distFile):
try:
tags = exifread.process_file(open(srcFile, 'rb')) # 获取照片的exif信息并更新需要写入的文字
except:
print("出错跳过")
else:
品牌 = ""
机型 = ""
镜头 = ""
logo_img = "logo/SONY.png"
快门 = ""
ISO = ""
光圈 = ""
焦距 = ""
if 'EXIF ISOSpeedRatings' in tags.keys():
ISO = "ISO" + str(tags['EXIF ISOSpeedRatings'])
if 'Image Make' in tags.keys():
品牌 = str(tags['Image Make'])
if 'Image Model' in tags.keys():
机型 = str(tags['Image Make']) + " " + str(tags['Image Model'])
if 'EXIF FNumber' in tags.keys():
fnum = float(Fraction(str(tags['EXIF FNumber'])))
光圈 = "f/" + str(fnum)
if 'EXIF ExposureTime' in tags.keys():
speed = Fraction(str(tags['EXIF ExposureTime']))
快门 = str(speed)
if 'EXIF FocalLengthIn35mmFilm' in tags.keys():
焦距 = str(tags['EXIF FocalLengthIn35mmFilm']) + "mm"
else:
焦距 = str(tags['EXIF FocalLength']) + "mm"
if 'EXIF LensModel' in tags.keys():
镜头 = str(tags['EXIF LensModel'])
else:
镜头 = ""
# 选择logo
if 品牌 == "SONY":
logo_img = "logo/SONY.png"
if 品牌 == "Panasonic":
logo_img = "logo/Lumix.png"
if 'Exif.Panasonic.LensType' in tags.keys():
镜头 = str(tags['EXIF LensModel'])
else:
镜头 = ""
if 品牌 == "vivo":
logo_img = "logo/ZEISS.png"
机型 = str(tags['Image Model'])
extime = Fraction(str(tags['EXIF ExposureTime'])).limit_denominator(300)
快门 = str(extime)
if 品牌 == "Canon":
logo_img = "logo/Canon.png"
机型 = str(tags['Image Model'])
if 品牌 == "NIKON CORPORATION":
logo_img = "logo/NIKON-2.png"
机型 = str(tags['Image Model'])
if 品牌 == "Xiaomi":
logo_img = "logo/leica.png"
机型 = str(tags['Image Model'])
if 机型 == "M2006J10C":
length = float(Fraction(str(tags['EXIF FocalLength'])))
焦距 = str(length) + "mm"
extime = Fraction(str(tags['EXIF ExposureTime'])).limit_denominator(300)
快门 = str(extime)
if 品牌 == "Google":
logo_img = "logo/Google.png"
extime = Fraction(str(tags['EXIF ExposureTime'])).limit_denominator(300)
快门 = str(extime)
if 品牌 == "PENTAX":
logo_img = "logo/PENTAX.png"
机型 = str(tags['Image Model'])
if 品牌 == "RICOH":
logo_img = "logo/PENTAX.png"
if 品牌 == "FUJIFILM":
logo_img = "logo/FUJIFILM.png"
if 品牌 == "GoPro":
logo_img = "logo/GoPro.png"
if 品牌 == "Olympus":
logo_img = "logo/Olympus.png"
if 品牌 == "PhaseOne":
logo_img = "logo/PhaseOne.png"
if 品牌 == "Hasselblad":
logo_img = "logo/Hasselblad.png"
if 品牌 == "HUAWEI":
logo_img = "logo/HUAWEI.png"
焦段 = 焦距 + " " + 光圈 + " " + 快门 + " " + ISO
# 打开原始照片
待处理照片 = Image.open(srcFile)
待处理照片 = ImageOps.exif_transpose(待处理照片)
待处理照片宽, 待处理照片高 = 待处理照片.size
# ========可设定参数
背景边框宽度 = 600
背景边框高度 = 500
高斯数值 = 15
#=========样式优化
水印横向偏置 = 待处理照片宽 / 8
# 创建模糊背景
模糊背景 = 待处理照片.copy()
模糊背景 = 模糊背景.filter(ImageFilter.GaussianBlur(高斯数值))
模糊背景 = 模糊背景.resize((待处理照片宽 + 背景边框宽度, 待处理照片高 + 背景边框高度), Image.Resampling.LANCZOS)
# 创建一个比原始照片大一些的新图像,添加模糊背景边框
背景图 = Image.new('RGB', (待处理照片宽 + 背景边框宽度, 待处理照片高 + 背景边框高度))
背景图.paste(模糊背景, (0, 0))
# 计算图片粘贴位置使其居中
paste_x = (背景图.width - 待处理照片宽) // 2
paste_y = (背景图.height - 待处理照片高 - 170) // 2 # 留出空间放水印
背景图.paste(待处理照片, (paste_x, paste_y))
# 在模糊背景上绘制水印
draw = ImageDraw.Draw(背景图)
# 绘制三段文字
font1 = ImageFont.truetype("font/Siemens Sans Bold.ttf", 84)
font2 = ImageFont.truetype("font/msyh.ttc", 60)
font3 = ImageFont.truetype("font/msyh.ttc", 78)
draw.text((paste_x + 水印横向偏置, paste_y + 待处理照片高 + 54), 机型, fill=(255, 255, 255, 255), font=font1) #164
draw.text((paste_x + 水印横向偏置, paste_y + 待处理照片高 + 154), 镜头, fill=(255, 255, 255, 255), font=font2)#164
draw.text((paste_x + 待处理照片宽 - 水印横向偏置 - 1000, paste_y + 待处理照片高 + 99), 焦段, fill=(255, 255, 255, 255), font=font3)#2708 焦段、光圈、iso信息;1000是这行字的宽度
# 绘制分隔线
分割线偏置 = 待处理照片宽 - 水印横向偏置 - 1000 - 54 #54是上面这段字和分隔线的距离
draw.line(((paste_x + 分割线偏置, paste_y + 待处理照片高 + 64), (paste_x + 分割线偏置, paste_y + 待处理照片高 + 236)), (197, 197, 197, 255), width=6)#2644 比上面小54
# 通过图片绘制logo
图标偏置 = int(分割线偏置 - 54 - 185)
if 机型 != "":
logo = Image.open(logo_img)
logo图片宽, logo图片高 = logo.size
if logo图片宽 > logo图片高:
背景图.paste(logo, (paste_x + 图标偏置, paste_y + 待处理照片高 + 62)) #2300
else:
背景图.paste(logo, (paste_x + 图标偏置, paste_y + 待处理照片高 + 62))
背景图.save(distFile, quality=100, exif=待处理照片.info['exif'])
print(srcFile, "已处理完成")
if __name__ == '__main__':
srcPath = 'images_intput'
distPath = 'images_output'
wrongpath = 'wrong'
parser = argparse.ArgumentParser(description="Add watermark to images")
parser.add_argument('color', type=str, help="Specify the border color (e.g., 'white')")
args = parser.parse_args()
color = args.color
watermark(srcPath, distPath, color)