当前位置:网站首页>图片批量添加水印批量缩放图片到指定大小
图片批量添加水印批量缩放图片到指定大小
2022-08-10 05:31:00 【DOCKER007】
达到的效果: 0.递归文件夹:按文件夹及下级文件夹进行递归 1.批量缩放:批量缩放图片大小(按指定模板图片大小缩放目标图片,并合并) 2.批量水印:批量把png格式的水印模板图片添加到指定图片 3.批量保存重命名:批量把图片另存为“原文件名+图片大小的”的图片 4.保存路径可选:保存路径可选择保留原路径,也可以与上级文件夹创建同级别的新文件夹存放新的图片 5.可重复执行不重复生成:用文件名区分,不会处理、不会重复生成文件名是“原文件名+图片大小的”的图片(重复执行会覆盖上次的执行结果,但不会把上次的执行结果图片重复处理,以文件名为主要区分) 执行方法在main中,有三种模式,推荐模式三
from PIL import Image
import os.path
import glob
import os,traceback
def convertjpg(jpgfile,outdir,width=1350,height=900):
img=Image.open(jpgfile)
try:
new_img = img.resize((width, height), Image.BILINEAR)
if new_img.mode == 'P':
new_img = new_img.convert("RGB")
if new_img.mode == 'RGBA':
new_img = new_img.convert("RGB")
new_img.save(os.path.join(outdir, os.path.basename(jpgfile)))
except Exception as e:
print(e)
def c_jpg():
total = 0
file_type = 'jpg'
for jpgfile in glob.glob(img_source_dir+'/*.'+file_type):
# print(jpgfile)
convertjpg(jpgfile,img_out_dir)
total = total+1
print('end. total='+total)
#####################################################################################################
#图片格式转换
def PNG_JPG(PngPath):
img = cv.imread(PngPath, 0)
w, h = img.shape[::-1]
infile = PngPath
outfile = os.path.splitext(infile)[0] + ".jpg"
img = Image.open(infile)
img = img.resize((int(w / 2), int(h / 2)), Image.ANTIALIAS)
try:
if len(img.split()) == 4:
# prevent IOError: cannot write mode RGBA as BMP
r, g, b, a = img.split()
img = Image.merge("RGB", (r, g, b))
img.convert('RGB').save(outfile, quality=70)
os.remove(PngPath)
else:
img.convert('RGB').save(outfile, quality=70)
os.remove(PngPath)
return outfile
except Exception as e:
print("PNG转换JPG 错误", e)
# 按模板把文件缩放图片 1:等比例缩放(固定宽和高) 2:按模板拉伸缩放,
def changeWHimg(img,markImg,mode=1):
#img = Image.open(img_file)
n_width = markImg.width
n_height = markImg.height
if mode == 1:
# 缩小
if img.width > markImg.width or img.height > markImg.height:
p_w = markImg.width / img.width
p_h = markImg.height / img.height
p = p_w if p_w < p_h else p_h # 确定比例,取最小值
n_width = int(p * img.width)
n_height = int(p * img.height)
print(img.filename, '太大了,等比例缩小', p, '倍以后是(', n_width, n_height, '),原来是(', img.width, img.height, ')')
#img = img.resize((n_width, n_height), Image.BILINEAR)
# 放大
if img.width < markImg.width - 1 and img.height < markImg.height - 1:
p_w = markImg.width / img.width
p_h = markImg.height / img.height
p = p_w if p_w < p_h else p_h # 确定比例,取最小值
n_width = int(p * img.width)
n_height = int(p * img.height)
print(img.filename, '太小,等比例放大', p, '倍以后是(', n_width, n_height, '),原来是(', img.width, img.height, ')')
elif mode ==2 :
p_w = markImg.width / img.width
p_h = markImg.height / img.height
p = p_w if p_w < p_h else p_h # 确定比例,取最小值
n_width = markImg.width
n_height = markImg.height
print(img.filename, ',拉伸缩放处理:宽width 高height 分别缩放', p_w,p_h, '倍以后是(', n_width, n_height, '),原来是(', img.width, img.height, ')')
else :
n_width = img.width
n_height = img.height
print('模式不对,保持原图,不作缩放处理')
#进行缩放处理
img = img.resize((n_width, n_height), Image.BILINEAR)
return img
# 保存图片
def saveImage(markImg,outdir,new_file):
outfile_path = os.path.dirname(new_file)
if not os.path.exists(outfile_path): # 如果路径不存在
os.makedirs(outfile_path)
markImg.save(new_file)
# markImg.show()
return True
# 设置文件名称
def getnewImagename(outfile_path,new_out_path,img_source):
stem, suffix = os.path.splitext(img_source) # 文件名 后缀
stem = os.path.basename(img_source).split('.')[0]
new_file = os.path.join(outfile_path, stem + new_out_path + suffix)
# print('新路径:', outfile_path,',新文件:',new_file)
return new_file
# 获取保存路径
def get_out_path(img_source,outdir,new_out_path):
# print('保存路径:',os.path.join(outdir, os.path.basename(img_source)) )
if outdir == '' or outdir is None or outdir == None:
parent_path = os.path.dirname(os.path.realpath(img_source)) # 获取其父目录
# print('父路径',parent_path,'当前路径',img_source,muban_w,muban_h)
outfile_path = parent_path + new_out_path # os.path.join(parent_path,out_pathkk) #
else:
outfile_path = outdir
return outfile_path
# 图片添加水印(png图片的水印),参数:Image 水印文件名
def img_water_mark(img, wm_file):
try:
watermark = Image.open(wm_file) # 打开水印
img_size = img.size
wm_size = watermark.size
# 如果图片大小小于水印大小
if img_size[0] < wm_size[0] or img_size[1] < wm_size[1] :
watermark.resize(tuple(map(lambda x: int(x * 0.5), watermark.size))) #重新设置水印图片大小
#watermark = changeWHimg(watermark,img) #缩放水印图片大小,与原图一样大小,等比例缩放
wm_size = watermark.size
#print('图片大小:', img_size,'水印大小',wm_size)
wm_position = (img_size[0]-wm_size[0],img_size[1]-wm_size[1]) # 默认设定水印位置为右下角
layer = Image.new('RGBA', img.size) # 新建一个图层
layer.paste(watermark, wm_position) # 将水印图片添加到图层上
mark_img = Image.composite(layer, img, layer)
return mark_img
except Exception as e:
print(traceback.print_exc())
#把图片与模板文件结合后
def addImg(img_source,muban_file,suofang = True):
if img_source == muban_file :
return None
img = Image.open(img_source)
markImg = Image.open(muban_file) #Image.new('RGBA',(img_w,img_h),'white')
muban_w = markImg.width
muban_h = markImg.height
#改变大小(适配效果)
if suofang :
img = changeWHimg(img,markImg)
x_width = int(0.5*markImg.width-0.5*img.width)
y_height = int(0.5*markImg.height - 0.5 *img.height)
x_width = x_width if x_width >0 and x_width < muban_w else 0
y_height = y_height if y_height >0 and y_height < muban_h else 0
#print('把文件',img_source,'放在',x_width,y_height )
#print('新文件大小是',markImg.width,',',markImg.height,',原文件大小是',img.width,',',img.height)
#合并图片:把img放在x y坐标处
markImg.paste(img,(x_width,y_height))
return markImg
# 遍历所有文件进行搜索
def search(root, target):
items = os.listdir(root)
for item in items:
path = os.path.join(root, item)
if os.path.isdir(path):
#print('[-]', path)
search(path, target)
elif path.split('/')[-1] == target:
print('[+]', path)
else:
print('[!]', path)
#print("获取当前文件路径——" + os.path.realpath(path)) # 获取当前文件路径
# parent = os.path.dirname(os.path.realpath(path)) # 获取其父目录
# print("获取其父目录——" + parent) # 从当前文件路径中获取目录
# garder = os.path.dirname(parent)
# print("获取父目录的父目录——" + garder)
continue
# 遍历所有文件夹,返回文件或文件夹
def get_alldirfile(root, type,alldir,allfile):
items = os.listdir(root)
for item in items:
path = os.path.join(root, item)
if os.path.isdir(path):
#print('[-]', path)
alldir.append(path)
get_alldirfile(path, type,alldir,allfile)
elif os.path.splitext(path)[1] == type :
#print('[+]', path,os.path.splitext(path)[1],type,os.path.splitext(path)[1] == type)
allfile.append(path)
else:
#print('[!]', path,os.path.splitext(path)[1])
continue
return alldir if type == '' else allfile
def get_alldir(root):
return get_alldirfile(root, '',[],[])
def get_allfiles(root, type):
return get_alldirfile(root, type,[],[])
# 遍历获取所有的文件(递归)
def show_files(s_path,all_files):
file_list = os.listdir(s_path) # 首先遍历当前目录所有文件及文件夹
# 准备循环判断每个元素是否是文件夹还是文件,是文件的话,把名称传入list,是文件夹的话,递归
for file in file_list :
# 利用os.path.join()方法取得路径全名,并存入cur_path变量,否则每次只能遍历一层目录
cur_path = os.path.join(s_path, file)
# 判断是否是文件夹
if os.path.isdir(cur_path):
show_files(cur_path, all_files)
else:
#all_files.append(file) #只记录文件名,不记录路径
all_files.append(cur_path) #记录全路径和文件名
return all_files
#把指定文件夹下的某类型图片合并(不递归)
def img_union(img_source_dir,img_types,muban_file,img_out_dir,suofang = True):
total = 0
shibai = 0
log_res = {}
for img_type in img_types :
type_total = 0
type_shibai = 0
type_hulue = 0
shibai_lilst = []
hulue_list = []
for jpgfile in glob.glob(img_source_dir + '/*' + img_type):
# print(jpgfile)
res_img = addImg(jpgfile, muban_file[img_type],suofang)
# 重新输出路径关键字
new_out_path_key = '-' + str(int(res_img.width)) + 'x' + str(int(res_img.height)) + 'px'
# 获取父路径并重命名父文件夹
outfile_path = get_out_path(jpgfile, img_out_dir, new_out_path_key)
if len(new_out_path_key) > 5 and new_out_path_key in jpgfile:
type_hulue = type_hulue + 1
hulue_list.append(jpgfile)
continue
# 重新设置文件名
new_file = getnewImagename(outfile_path, new_out_path_key,
jpgfile) # os.path.join(outfile_path, stem + new_out_path_key + suffix)
# 保存文件
save_flag = saveImage(res_img, outfile_path, new_file)
if res_img is not None and save_flag:
total = total + 1
type_total = type_total + 1
# saveImage(res_img)
else:
shibai = shibai + 1
type_shibai = type_shibai + 1
shibai_lilst.append(jpgfile)
log_res[img_type] = {'成功':type_total,'失败':type_shibai,'忽略':type_hulue,'失败列表':shibai_lilst,'忽略列表':hulue_list}
print(img_type, 'end. 一共完成', type_total, '张图片的转换工作,其中', type_shibai, '张失败')
print(img_type, '失败列表', shibai_lilst)
print(img_types, 'end. 一共完成', total, '张图片的转换工作,其中', shibai, '张失败')
print(log_res)
#把指定文件夹下的某类型图片合并(递归所有子文件)
def img_union_all(root,img_types,muban_file,img_out_dir,shuiyin = None,suofang = True):
total = 0
shibai = 0
log_res = {}
for img_type in img_types:
type_total = 0
type_shibai = 0
type_hulue = 0
shibai_lilst = []
hulue_list = []
for jpgfile in get_allfiles(root,img_type) : #glob.glob(img_source_dir + '/*' + img_type):
# print(jpgfile)
#print('模板:',muban_file[img_type],',原文件:',jpgfile)
# addImg(jpgfile, img_out_dir, muban_file[img_type])
res_img = addImg(jpgfile, muban_file[img_type],suofang)
#加水印图片
if shuiyin != None and os.path.exists(shuiyin):
#水印模板文件如果存在,则直接添加水印效果
res_img = img_water_mark(res_img,shuiyin)
elif shuiyin != None and shuiyin != '' :
#文字水印,暂时忽略(先制作png格式的水印图片,然后使用水印模板加入水印效果)
res_img = res_img
else:
continue;
#重新输出路径关键字
new_out_path_key = '-' + str(int(res_img.width)) + 'x' + str(int(res_img.height)) + 'px'
#获取父路径并重命名父文件夹
outfile_path = get_out_path(jpgfile,img_out_dir,new_out_path_key)
if len(new_out_path_key) > 5 and new_out_path_key in jpgfile:
type_hulue = type_hulue+1
hulue_list.append(jpgfile)
continue
#重新设置文件名
new_file = getnewImagename(outfile_path,new_out_path_key,jpgfile) #os.path.join(outfile_path, stem + new_out_path_key + suffix)
#保存文件
save_flag = saveImage(res_img,outfile_path,new_file)
if res_img is not None and save_flag :
total = total + 1
type_total = type_total+1
#saveImage(res_img)
else:
shibai = shibai+1
type_shibai = type_shibai+1
shibai_lilst.append(jpgfile)
log_res[img_type] = {'成功':type_total,'失败':type_shibai,'忽略':type_hulue,'失败列表':shibai_lilst,'忽略列表':hulue_list}
print(img_type, 'end. 一共完成', type_total, '张图片的转换工作,其中', type_shibai, '张失败')
print(img_type,'失败列表',shibai_lilst)
print(img_types, 'end. 一共完成', total, '张图片的转换工作,其中', shibai, '张失败')
print(log_res)
if __name__ == '__main__':
#################################################################################################################################
###模式三:递归遍历所有文件夹和子文件夹,并把图片与模板贴合,并添加水印
root_dir = 'E:\教材\教材封面V2' # 根目录
img_types = ['.jpg', '.png'] # 图片类型
img_out_dir = 'E:\教材\教材封面V2\语文' # 输出路径:空代表与上级目录同级自动创建文件夹新建,如设置值则统一放在指定位置 'E:\教材\人教版-义务教育教科书-1350x900px'
muban_file = {'.jpg': 'E:\教材\模板1-1530x900.jpg',
'.png': 'E:\教材\模板2-1530x900.png'} # 各类型的模板文件,必须设置相同类型问文件模板 'E:\教材\模板.jpg'
suofang = True # 是否缩放(按照模板大小等比例缩放图片)
shuiyin = 'E:\\教材\\水印2.png' #是否设置水印(水印模板文件),可以是None表示不加水印
print("path: " + root_dir)
# 开始
img_union_all(root_dir, img_types, muban_file, img_out_dir, shuiyin, suofang) # 把指定路径下某类型文件图片按模板合并 输出到指定路径(空路径会自动创建)
#################################################################################################################################
#################################################################################################################################
###模式二:递归遍历所有文件夹和子文件夹,并把图片与模板贴合
# root_dir = 'E:\\教材\\课本封面素材\\课本封面素材' #根目录
# img_types = ['.jpg', '.png'] #图片类型
# img_out_dir = '' #输出路径:空代表与上级目录同级自动创建文件夹新建,如设置值则统一放在指定位置 'E:\教材\人教版-义务教育教科书-1350x900px'
# muban_file = {'.jpg': 'E:\教材\模板1-1530x900.jpg', '.png': 'E:\教材\模板2-1530x900.png'} #各类型的模板文件,必须设置相同类型问文件模板 'E:\教材\模板.jpg'
# suofang = True # 是否缩放(按照模板大小等比例缩放图片)
# shuiyin = None #'E:\\教材\\水印.png' #是否设置水印,可以是None表示不加水印
# print("path: " + root_dir)
# #开始
# img_union_all(root_dir, img_types, muban_file, '', shuiyin, suofang) # 把指定路径下某类型文件图片按模板合并 输出到指定路径(空路径会自动创建)
#################################################################################################################################
#################################################################################################################################
###模式一:把文件夹下的图片与模板贴合(忽略子目录下级文件)
# img_source_dir = 'E:\\教材\\课本封面素材\\课本封面素材\\01.语文课本封面\\初中' #指定文件夹(不含子文件夹,不会穿透下级目录)
# img_types = ['.jpg', '.png'] # 图片类型
# img_out_dir = '' # 输出路径:空代表与上级目录同级自动创建文件夹新建,如设置值则统一放在指定位置 'E:\教材\人教版-义务教育教科书-1350x900px'
# muban_file = {'.jpg': 'E:\\教材\\模板2.jpg', '.png': 'E:\\教材\\模板3.png'} # 各类型的模板文件,必须设置相同类型问文件模板 'E:\教材\模板.jpg'
# suofang = True # 是否缩放(按照模板大小等比例缩放图片)
# shuiyin = 'E:\\教材\\水印.png'
# print("path: " + img_source_dir)
# img_union(img_source_dir,img_types,muban_file,img_out_dir,suofang) #把指定路径下某类型文件图片按模板合并 输出到指定路径(空路径会自动创建)
#################################################################################################################################
# all_files = show_files(root_dir,[])
# print(all_files) #打印所有文件
# search(root_dir,'') # 打印所有文件 和文件夹
# print('文件夹:', get_alldir(root_dir) ) # 文件夹
# print('文件', get_allfiles(root_dir,'.jpg') ) # 文件
# search(root_dir,'语文八年级上册')
边栏推荐
猜你喜欢
深度学习中的学习率调整策略(1)
pytorch框架学习(7) tensorboard使用
论文精度 —— 2016 CVPR 《Context Encoders: Feature Learning by Inpainting》
在yolov5的网络结构中添加注意力机制模块
Interface debugging also can play this?
OneFlow源码解析:算子指令在虚拟机中的执行
速刷正则表达式一周目(上)
Read the excerpt notes made by dozens of lightweight target detection papers for literacy
YOLOv5 PyQt5(一起制作YOLOv5的GUI界面)
Kubernetes:(十六)Ingress的概念和原理
随机推荐
基本比例尺标准分幅编号流程
redis---非关系型数据库(NoSql)
每周推荐短视频:探索AI的应用边界
【el和template区别】
Tkinter 入门之旅
Pony语言学习(一):环境配置(续)
Kubernetes:(十七)Helm概述、安装及配置
深度学习模型训练前的必做工作:总览模型信息
清览题库--C语言程序设计第五版编程题解析(1)
定时器(setInterval)的开启与关闭
idm下载器如何使用 idm下载器使用技巧
智能合约和去中心化应用DAPP
Pony语言学习(七)——表达式(Expressions)语法(单篇向)
pytorch框架学习(7) tensorboard使用
在yolov5的网络结构中添加注意力机制模块
每天一个小知识点
Interface documentation evolution illustration, some ancient interface documentation tools, you may not have used it
微信小程序wx.writeBLECharacteristicValue汉字转buffer问题
OpenGauss source code, is it maintained with VSCode in the window system?
文章复现:超分辨率网络-VDSR