python3一键排版证件照(一寸照、二寸照),附源代码
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了python3一键排版证件照(一寸照、二寸照),附源代码,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含11602字,纯文字阅读大概需要17分钟。
内容图文
又到了一年一度办公园年卡的日子了,每年需要一张一寸照片,库存今年告罄
如果拿着一寸照片去冲印,商家那个冲印的价格可比冲印普通照片不知道贵了多少呗(目测10倍以上)
其实是一样的相纸啊
于是乎,为了省这点钱就自己排版好了
如果选用工具的话,不会ps的推荐“光影魔术手v3.1.2”(最新版感觉不太好用)
but,作为一个技术宅,我当然是选择自己来实现啦!
话不多说,说干就干
思路:
1. 首先需要一张已经拍摄好的证件照,尺寸比例可以不完全按照标准
2. 按比例裁剪(1寸、2寸的比例不同)
3. 缩放到标准尺寸
4. 排版到5寸或者6寸照片上
照片尺寸:宽*高(单位:像素)
1寸照片:295*413
2寸照片:413*626
5寸照片(横版):1500*1050
6寸照片(横版):1800*1200
环境:
python3 + pillow库
具体操作:
1. 裁剪
以1寸照片为例,其高:宽 = 1.4,为了使原始照片不失真,应该按照这个1.4的比例进行裁剪
若大于1.4说明高度多了,需要进行上下裁剪;若小于1.4说明宽度多了,需要进行左右裁剪。这里的裁剪均是对称平均裁剪
Image.crop((left, up, right, below))
参数:
需要四个参数,分别是目标照片的四个边线距离左边和上边的距离
值得注意的是:参数是一个元组,因此看起来有两对括号!
2. 缩放
将已经调整好比例的照片进行标准缩放,标准如下(单位:像素):
1寸照片:295*413
2寸照片:413*626
Image.resize(width, height)
参数:
width:宽
heght:高
3. 排版
先想好冲印5寸照片还是6寸照片,以及是需要1寸、2寸还是混合排版
这两个因素都会影响到排版问题,主要是横or竖的问题
以5寸照片上排版1寸照片为例(5寸横版,1寸竖版,2*4排列),是这样滴:
在排列之前,我细心的用画笔画出了裁剪线,这样手残的人再也不用哆哆嗦嗦剪歪了
bk = Image.new("RGB", [WIDTH_5IN,HEIGHT_5IN], (255,255,255))# 创建一个5寸大小的,白色背景的画板 draw = ImageDraw.Draw(bk)# 创建画笔 draw.line([(0,HEIGHT_5IN/2),(WIDTH_5IN,HEIGHT_5IN/2)],fill=128) # 横线,fill是填充颜色
新建画板就不多讲了,注意一下参数的位置,先宽后高,颜色参数其实有多种写法
这里主要讲一下怎么在画板上画线,其实是需要起点坐标和终点坐标,坐标原点是画板左上角,横轴向右x,纵轴向下y
还是画个图更直观
注意坐标的写法 [(起点x,起点y),(终点x,终点y)],坐标点必须为int类型
我这个画完是这样嘞:
然后就是把照片贴上去,注意要放在每个“格子”的中心呦
Image.paste(photo, (photo左上角坐标))
因此,我们需要计算单个1寸照片在整个画板里左上角坐标,还是画个图说明下:
先求每个小格子里中心点focus_point的坐标,然后根据1寸照片的大小求左上角坐标start_point
然后根据每个start_point循环把照片贴上去就好啦!
我生成的是这样嘞,看起来很完美啊!
同理,5寸照片排版2寸的。这里注意新建画板时候的尺寸,因为相当于是竖版照片
5寸照片混合排列1寸、2寸的:
这里注意一下:
2寸照片旋转了90度,用到的函数中,参数必须写上expand=True
Image.rotate(90,expand=True))
如果没写这个参数默认是False,这样旋转后的照片是按照原来的大小,会有裁剪或者黑边,例如:
6寸照片排版1寸:
6寸照片排版2寸按照5寸照片的排版模式会有高度上的溢出
同理,6寸照片混合排列1寸、2寸的也是有溢出
解决方法:新建画布时候按照6寸比例3:2进行适当的放大,因为冲印的时候也没要求就是标准大小嘛
比如,我将大小改为1950*1300
同理,6寸照片混合排列1寸、2寸的也是有溢出。修改完尺寸,混合排版的样子就多了去了,比如:
源代码:
感觉写的有点啰嗦了,应该使用对象的方法精简一下,很多重复的代码改起来也很麻烦
1 # Author:ZM 2 3 """ 4 照片尺寸,宽*高(单位:像素) 5 1寸照片:295*413 6 2寸照片:413*626 7 5寸照片(横版):1500*1050 8 6寸照片(横版):1800*1200 9 """ 10 from PIL import Image,ImageDraw 11 12 WIDTH_1IN = 295 13 HEIGHT_1IN = 413 14 15 WIDTH_2IN = 413 16 HEIGHT_2IN = 626 17 18 WIDTH_5IN = 1500 19 HEIGHT_5IN = 1050 20 21# 非全景6寸照片 22 WIDTH_6IN = 1950 23 HEIGHT_6IN = 1300 24 25def cut_photo(photo,choice): 26""" 27 将照片按照比例进行裁剪成1寸、2寸 28 :param photo: 待处理的照片 29 :param choice: <int> 1代表1寸,2代表2寸 30 :return: 处理后的照片 31""" 32 width = photo.size[0] # 宽 33 height = photo.size[1] #高 34 rate = height / width 35if choice == 1: 36if rate < (HEIGHT_1IN/WIDTH_1IN): 37 x = (width - int(height / HEIGHT_1IN * WIDTH_1IN)) / 2 38 y = 0 39 cutted_photo = photo.crop((x, y, x + (int(height / HEIGHT_1IN * WIDTH_1IN)), y + height)) 40 41else: 42 x = 0 43 y = (height - int(width / WIDTH_1IN * HEIGHT_1IN)) / 2 44 cutted_photo = photo.crop((x, y, x + width, y + (int(width / WIDTH_1IN * HEIGHT_1IN)))) 45return cutted_photo 46 47if choice == 2: 48if rate < (HEIGHT_2IN/WIDTH_2IN): 49 x = (width - int(height / HEIGHT_2IN * WIDTH_2IN)) / 2 50 y = 0 51 cutted_photo = im.crop((x, y, x + (int(height / HEIGHT_2IN * WIDTH_2IN)), y + height)) 52 53else: 54 x = 0 55 y = (height - int(width / WIDTH_2IN * HEIGHT_2IN)) / 2 56 cutted_photo = im.crop((x, y, x + width, y + (int(width / WIDTH_2IN * HEIGHT_2IN)))) 57 58return cutted_photo 59 60def resize_photo(photo,choice): 61‘‘‘ 62 缩放照片 63 :param photo: 待处理的照片 64 :param choice: <int> 1代表1寸,2代表2寸 65 :return: 处理后的照片 66‘‘‘ 67if choice == 1: 68 resized_photo = photo.resize((WIDTH_1IN,HEIGHT_1IN)) 69return resized_photo 70if choice == 2: 71 resized_photo = photo.resize((WIDTH_2IN, HEIGHT_2IN)) 72return resized_photo 73 74 75def layout_photo_5_1(photo): 76""" 77 在5寸照片上排版1寸照片 78 :param photo: 待处理照片1寸 79 :return: 处理后的照片 80""" 81 bk = Image.new("RGB", [WIDTH_5IN,HEIGHT_5IN], (255,255,255)) 82 draw = ImageDraw.Draw(bk)# 创建画笔 83 draw.line([(0,HEIGHT_5IN/2),(WIDTH_5IN,HEIGHT_5IN/2)],fill=128) # 横线 84 draw.line([(WIDTH_5IN*0.25,0),(WIDTH_5IN*0.25,HEIGHT_5IN)],fill=128) # 第1条竖线 85 draw.line([(WIDTH_5IN*0.5,0),(WIDTH_5IN*0.5,HEIGHT_5IN)],fill=128) # 第2条竖线 86 draw.line([(WIDTH_5IN*0.75,0),(WIDTH_5IN*0.75,HEIGHT_5IN)],fill=128) # 第3条竖线 87 88 focus_point = [0.125 * WIDTH_5IN,0.25 * HEIGHT_5IN] 89 start_point = [focus_point[0] - 0.5 * WIDTH_1IN, focus_point[1] - 0.5 * HEIGHT_1IN] 90for i in range(0,2): 91for k in range(0,4): 92 bk.paste(photo, (int(start_point[0] + (k * WIDTH_5IN / 4)), int(start_point[1] + 0.5 * i * HEIGHT_5IN))) 93return bk 94 95 96def layout_photo_5_2(photo): 97""" 98 在5寸照片上排版2寸照片 99 :param photo: 待处理照片2寸 100 :return: 处理后的照片 101"""102 bk = Image.new("RGB", [HEIGHT_5IN,WIDTH_5IN], (255,255,255)) # 竖版排版103# 创建画笔104 draw = ImageDraw.Draw(bk) 105 draw.line([(0,WIDTH_5IN/2),(WIDTH_5IN,WIDTH_5IN/2)],fill=128) # 横线106 draw.line([(HEIGHT_5IN*0.5,0),(HEIGHT_5IN*0.5,WIDTH_5IN)],fill=128) # 竖线107 focus_point = [0.25 * HEIGHT_5IN, 0.25 * WIDTH_5IN] 108 start_point = [focus_point[0] - 0.5 * WIDTH_2IN, focus_point[1] - 0.5 * HEIGHT_2IN] 109#print(focus_point,start_point)110for i in range(0,2): 111for k in range(0,2): 112 bk.paste(photo, (int(start_point[0] + (k * HEIGHT_5IN / 2)), int(start_point[1] + 0.5* i * WIDTH_5IN))) 113return bk 114115def layout_photo_5_mix(photo1,photo2): 116"""117 在5寸照片上混合排版1寸、2寸照片 118 :param photo1: 待处理照片1寸 119 :param photo1: 待处理照片2寸 120 :return: 处理后的照片 121"""122 bk = Image.new("RGB", [WIDTH_5IN,HEIGHT_5IN], (255,255,255)) 123# 创建画笔124 draw = ImageDraw.Draw(bk) 125 draw.line([(0,HEIGHT_5IN/2),(WIDTH_5IN,HEIGHT_5IN/2)],fill=128) # 横线126 draw.line([(WIDTH_5IN*0.25,0),(WIDTH_5IN*0.25,HEIGHT_5IN)],fill=128) # 第1条竖线127 draw.line([(WIDTH_5IN*0.5,0),(WIDTH_5IN*0.5,HEIGHT_5IN)],fill=128) # 第2条竖线128129 focus_point = [0.125 * WIDTH_5IN,0.25 * HEIGHT_5IN] 130 start_point = [focus_point[0] - 0.5 * WIDTH_1IN, focus_point[1] - 0.5 * HEIGHT_1IN] 131 focus_point2 = [0.75 * WIDTH_5IN, 0.25 * HEIGHT_5IN] 132 start_point2 = [focus_point2[0] - 0.5 * HEIGHT_2IN, focus_point2[1] - 0.5 * WIDTH_2IN] 133134for i in range(0,2): 135for k in range(0,2): 136 bk.paste(photo1, (int(start_point[0] + (k * WIDTH_5IN / 4)), int(start_point[1] + 0.5 * i * HEIGHT_5IN))) 137138 bk.paste(photo2,(int(start_point2[0]),int(start_point2[1]))) 139 bk.paste(photo2,(int(start_point2[0]),int(start_point2[1] + 0.5 * HEIGHT_5IN))) 140return bk 141142def layout_photo_6_1(photo): 143"""144 在6寸照片上排版2寸照片 145 :param photo: 待处理照片1寸 146 :return: 处理后的照片 147"""148 bk = Image.new("RGB", [HEIGHT_6IN,WIDTH_6IN], (255,255,255)) # 竖版排版149# 创建画笔150 draw = ImageDraw.Draw(bk) 151 draw.line([(0,WIDTH_6IN*0.25),(WIDTH_6IN,WIDTH_6IN*0.25)],fill=128) # 横线152 draw.line([(0,WIDTH_6IN*0.5),(WIDTH_6IN,WIDTH_6IN*0.5)],fill=128) # 横线153 draw.line([(0,WIDTH_6IN*0.75),(WIDTH_6IN,WIDTH_6IN*0.75)],fill=128) # 横线154 draw.line([(HEIGHT_6IN*0.25,0),(HEIGHT_6IN*0.25,WIDTH_6IN)],fill=128) # 竖线155 draw.line([(HEIGHT_6IN*0.5,0),(HEIGHT_6IN*0.5,WIDTH_6IN)],fill=128) # 竖线156 draw.line([(HEIGHT_6IN*0.75,0),(HEIGHT_6IN*0.75,WIDTH_6IN)],fill=128) # 竖线157 focus_point = [0.125 * HEIGHT_6IN, 0.125 * WIDTH_6IN] 158 start_point = [focus_point[0] - 0.5 * WIDTH_1IN, focus_point[1] - 0.5 * HEIGHT_1IN] 159#print(focus_point,start_point)160for i in range(0,4): 161for k in range(0,4): 162 bk.paste(photo, (int(start_point[0] + (k * HEIGHT_6IN / 4)), int(start_point[1] + i * 0.25 * WIDTH_6IN ))) 163return bk 164165def layout_photo_6_2(photo): 166"""167 在6寸照片上排版2寸照片 168 :param photo: 待处理照片2寸 169 :return: 处理后的照片 170"""171 bk = Image.new("RGB", [WIDTH_6IN,HEIGHT_6IN], (255,255,255)) 172# 创建画笔173 draw = ImageDraw.Draw(bk) 174 draw.line([(0,HEIGHT_6IN/2),(WIDTH_6IN,HEIGHT_6IN/2)],fill=128) # 横线175 draw.line([(WIDTH_6IN*0.25,0),(WIDTH_6IN*0.25,HEIGHT_6IN)],fill=128) # 第1条竖线176 draw.line([(WIDTH_6IN*0.5,0),(WIDTH_6IN*0.5,HEIGHT_6IN)],fill=128) # 第2条竖线177 draw.line([(WIDTH_6IN*0.75,0),(WIDTH_6IN*0.75,HEIGHT_6IN)],fill=128) # 第3条竖线178 focus_point = [0.125 * WIDTH_6IN,0.25 * HEIGHT_6IN] 179 start_point = [focus_point[0] - 0.5 * WIDTH_2IN, focus_point[1] - 0.5 * HEIGHT_2IN] 180for i in range(0,2): 181for k in range(0,4): 182 bk.paste(photo, (int(start_point[0] + (k * WIDTH_6IN / 4)), int(start_point[1] + 0.5 * i * HEIGHT_6IN))) 183return bk 184185186def layout_photo_6_mix1(photo1,photo2): 187"""188 在6寸照片上混合排版1寸、2寸照片 189 :param photo1: 待处理照片1寸 190 :param photo1: 待处理照片2寸 191 :return: 处理后的照片 192"""193 bk = Image.new("RGB", [WIDTH_6IN,HEIGHT_6IN], (255,255,255)) 194# 创建画笔195 draw = ImageDraw.Draw(bk) 196 draw.line([(0,HEIGHT_6IN*0.5),(WIDTH_6IN,HEIGHT_6IN/2)],fill=128) # 横线197 draw.line([(0,HEIGHT_6IN*0.25),(WIDTH_6IN*0.5,HEIGHT_6IN*0.25)],fill=128) # 短横线198 draw.line([(0,HEIGHT_6IN*0.75),(WIDTH_6IN*0.5,HEIGHT_6IN*0.75)],fill=128) # 短横线199 draw.line([(WIDTH_6IN*0.25,0),(WIDTH_6IN*0.25,HEIGHT_6IN)],fill=128) # 第1条竖线200 draw.line([(WIDTH_6IN*0.5,0),(WIDTH_6IN*0.5,HEIGHT_6IN)],fill=128) # 第2条竖线201 draw.line([(WIDTH_6IN*0.75,0),(WIDTH_6IN*0.75,HEIGHT_6IN)],fill=128) # 第3条竖线202 focus_point = [0.125 * WIDTH_6IN, 0.125 * HEIGHT_6IN] 203 start_point = [focus_point[0] - 0.5 * HEIGHT_1IN, focus_point[1] - 0.5 * WIDTH_1IN] 204for i in range(0,4): 205for k in range(0,2): 206 bk.paste(photo1, (int(start_point[0] + (0.25 * k * WIDTH_6IN )), int(start_point[1] + 0.25 * i * HEIGHT_6IN))) 207 focus_point2 = [0.625 * WIDTH_6IN, 0.25 * HEIGHT_6IN] 208 start_point2 = [focus_point2[0] - 0.5 * WIDTH_2IN, focus_point2[1] - 0.5 * HEIGHT_2IN] 209for i in range(0,2): 210for k in range(0,2): 211 bk.paste(photo2,(int(start_point2[0] + (0.25 * k * WIDTH_6IN)), int(start_point2[1] + 0.5 * i * HEIGHT_6IN))) 212 bk.show() 213return bk 214215216217def layout_photo_6_mix2(photo1,photo2): 218"""219 在6寸照片上混合排版1寸、2寸照片 220 :param photo1: 待处理照片1寸 221 :param photo1: 待处理照片2寸 222 :return: 处理后的照片 223"""224 bk = Image.new("RGB", [HEIGHT_6IN,WIDTH_6IN], (255,255,255)) # 竖版排版225# 创建画笔226 draw = ImageDraw.Draw(bk) 227228 draw.line([(350,0),(350,WIDTH_6IN)],fill=128) # 竖线229 draw.line([(700,0),(700,WIDTH_6IN)],fill=128) # 竖线230231232 draw.line([(0,WIDTH_6IN*0.25),(700,WIDTH_6IN*0.25)],fill=128) # 横线1233 draw.line([(0,WIDTH_6IN*0.5),(700,WIDTH_6IN*0.5)],fill=128) # 横线2234 draw.line([(0,WIDTH_6IN*0.75),(700,WIDTH_6IN*0.75)],fill=128) # 横线3235 draw.line([(700,WIDTH_6IN/3),(HEIGHT_6IN,WIDTH_6IN/3)],fill=128) # 横线4236 draw.line([(700,WIDTH_6IN*2/3),(HEIGHT_6IN,WIDTH_6IN*2/3)],fill=128) # 横线5237238 focus_point = [0.5 * 350, 0.125 * WIDTH_6IN] 239 start_point = [focus_point[0] - 0.5 * WIDTH_1IN, focus_point[1] - 0.5 * HEIGHT_1IN] 240241#print(focus_point,start_point)242for i in range(0,4): 243for k in range(0,2): 244 bk.paste(photo1, (int(start_point[0] + (k * 350)), int(start_point[1] + i * 0.25 * WIDTH_6IN ))) 245246 focus_point2 = [0.5 * HEIGHT_6IN+350, WIDTH_6IN/6] 247 start_point2 = [focus_point2[0] - 0.5 * WIDTH_2IN, focus_point2[1] - 0.5 * HEIGHT_2IN] 248for i in range(0,3): 249 bk.paste(photo2, (int(start_point2[0]), int(start_point2[1] + i * WIDTH_6IN /3))) 250return bk 251252253 im = Image.open(‘xzk2.jpg‘) 254 width = im.size[0] 255 height = im.size[1] 256 rate = height / width 257 layout_photo_5_1(resize_photo(cut_photo(im,1),1)).save(‘5_1.jpg‘) 258 layout_photo_5_2(resize_photo(cut_photo(im,2),2)).save(‘5_2.jpg‘) 259 layout_photo_6_1(resize_photo(cut_photo(im,1),1)).save(‘6_1.jpg‘) 260 layout_photo_6_2(resize_photo(cut_photo(im,2),2)).save(‘6_2.jpg‘) 261 layout_photo_5_mix(resize_photo(cut_photo(im,1),1),resize_photo(cut_photo(im,2),2).rotate(90,expand=True)).save(‘5_1_mix.jpg‘) 262 layout_photo_6_mix1(resize_photo(cut_photo(im,1),1).rotate(90,expand=True),resize_photo(cut_photo(im,2),2)).save(‘6_mix1.jpg‘) 263 layout_photo_6_mix2(resize_photo(cut_photo(im,1),1),resize_photo(cut_photo(im,2),2)).save(‘6_mix2.jpg‘)
最后,感谢薛老板友情出镜!
原文:https://www.cnblogs.com/aby321/p/11805789.html
内容总结
以上是互联网集市为您收集整理的python3一键排版证件照(一寸照、二寸照),附源代码全部内容,希望文章能够帮你解决python3一键排版证件照(一寸照、二寸照),附源代码所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。