导读
项目中需要用到图片批量化处理,所以玩了下PIL做了个简单的小项目,解放双手批量制作淘宝主图的功能
任务目标
- 根据传入的图片数量,自动放大缩小寻找计算可对齐的中心点进行裁切
- 按照传入图片数量,定制化排版图片
- 生成模糊背景,以及标题遮罩,根据输入的文字标题信息,自动定位排版标题位置
效果预览及核心代码逻辑
- 如果只传入一张图片的话,展示效果,包括核心代码实现
# 如果传入一张图片 就复制一份在中间缩略 另外一张底部平铺模糊
if(num == 1):
new_im = self.resizeImage(ims[0],bw,bh)
ft.paste(new_im, (0, 0)) # 模糊底图
pass
- 如果传入两张图片的话,展示效果,包括核心代码实现
# 如果传入两张图片 就在对角各展示一张
elif(num == 2):
scale = 0.5
new_im_1 = self.resizeImage(ims[0],int(bw*scale),int(bh*scale))
new_im_1_copy = new_im_1.copy()
new_im_2 = self.resizeImage(ims[1],int(bw*scale),int(bh*scale))
new_im_2_copy = new_im_2.copy()
ft.paste(new_im_1, (-lineW, -lineW)) #左上
ft.paste(new_im_2, (int(bw*scale)+lineW, -lineW)) #右上
ft.paste(new_im_2, (-lineW, int(bh*scale)+lineW)) #左下
ft.paste(new_im_1, (int(bw*scale)+lineW, int(bh*scale)+lineW)) #右下
pass
- 如果传入的是三张图片 横着两张 竖着三张排列
# 如果传入的是三张图片
elif(num == 3):
xw = int(bw/2)
xh = int(bh/num)
new_im_1 = self.resizeImage(ims[0],xw,xh)
new_im_2 = self.resizeImage(ims[1],xw,xh)
new_im_3 = self.resizeImage(ims[2],xw,xh)
ft.paste(new_im_1, (-lineW, -lineW)) #左上
ft.paste(new_im_3, (xw+lineW, -lineW)) #右上
ft.paste(new_im_2, (-lineW, xh+lineW)) #中左
ft.paste(new_im_1, (xw+lineW, xh+lineW)) #中右
ft.paste(new_im_3, (-lineW, xh*2+lineW*2)) #下左
ft.paste(new_im_2, (xw+lineW, xh*2+lineW*2)) #下右
- 如果传入的是四张图片
# 如果传入的是四张图片
elif(num == 4):
xw1 = int(bw*0.6)
xh1 = int(bh*0.5)
xw2 = int(bw*0.4)
xh2 = int(bh*0.4)
xh3 = int(bh*0.6)
new_im_1 = self.resizeImage(ims[0],xw1,xh1)
new_im_2 = self.resizeImage(ims[1],xw1,xh1)
new_im_3 = self.resizeImage(ims[2],xw2,xh3)
new_im_4 = self.resizeImage(ims[3],xw2,xh2)
ft.paste(new_im_1, (-lineW, -lineW)) #左上
ft.paste(new_im_4, (xw1+lineW, -lineW)) #右上
ft.paste(new_im_2, (-lineW, xh1+lineW*2)) #下左
ft.paste(new_im_3, (xw1+lineW, xh2+lineW*2)) #下右
- 如果传入的是五张图片
# 如果传入的是5张图片
elif(num == 5):
xw1 = int(bh*0.5)
xh1 = int(bh*0.33333)
xh2 = int(bh*0.5)
new_im_1 = self.resizeImage(ims[0],xw1,xh1)
new_im_2 = self.resizeImage(ims[1],xw1,xh1)
new_im_3 = self.resizeImage(ims[2],xw1,xh1)
new_im_4 = self.resizeImage(ims[3],xw1,xh2)
new_im_5 = self.resizeImage(ims[4],xw1,xh2)
ft.paste(new_im_1, (-lineW, -lineW))
ft.paste(new_im_2, (-lineW, xh1+lineW))
ft.paste(new_im_3, (-lineW, (xh1+lineW)*2))
ft.paste(new_im_4, (xw1+lineW, xh2+lineW))
ft.paste(new_im_5, (xw1+lineW, -lineW))
pass
- 如果传入的是六张图片
# 如果传入的是6张图片
elif(num == 6):
xw1 = int(bw*0.5)
xh1 = int(bh*0.65)
xw2 = int(bw*0.25)
xh2 = int(bh*0.35)
new_im_1 = self.resizeImage(ims[0],xw1,xh1)
new_im_2 = self.resizeImage(ims[1],xw1,xh1)
new_im_3 = self.resizeImage(ims[2],xw2,xh2)
new_im_4 = self.resizeImage(ims[3],xw2,xh2)
new_im_5 = self.resizeImage(ims[4],xw2,xh2)
new_im_6 = self.resizeImage(ims[5],xw2,xh2)
ft.paste(new_im_1, (-lineW, -lineW))
ft.paste(new_im_2, (xw1+lineW, -lineW))
ft.paste(new_im_3, (-lineW*3, xh1+lineW))
ft.paste(new_im_4, (xw2-lineW, xh1+lineW))
ft.paste(new_im_5, (xw2*2+lineW, xh1+lineW))
ft.paste(new_im_6, (xw2*3+lineW*3, xh1+lineW))
pass
- 如果传入的是七张图片
# 如果传入的是7张图片
elif(num == 7):
xw1 = int(bw*0.5)
xh1 = int(bh*0.3333)
xw2 = bw
xw3 = int(bw*0.25)
new_im_1 = self.resizeImage(ims[0],xw1,xh1)
new_im_2 = self.resizeImage(ims[1],xw1,xh1)
new_im_3 = self.resizeImage(ims[2],xw2,xh1)
new_im_4 = self.resizeImage(ims[3],xw3,xh1)
new_im_5 = self.resizeImage(ims[4],xw3,xh1)
new_im_6 = self.resizeImage(ims[5],xw3,xh1)
new_im_7 = self.resizeImage(ims[6],xw3,xh1)
ft.paste(new_im_1, (-lineW, -lineW))
ft.paste(new_im_2, (xw1+lineW, -lineW))
ft.paste(new_im_3, (0, xh1+lineW))
ft.paste(new_im_4, (-lineW, (xh1+lineW)*2))
ft.paste(new_im_5, (xw3, (xh1+lineW)*2))
ft.paste(new_im_6, (xw3*2+lineW, (xh1+lineW)*2))
ft.paste(new_im_7, (xw3*3+lineW*2, (xh1+lineW)*2))
pass
- 如果传入的是八张图片
# 如果传入的是8张图片
elif(num == 8):
xw1 = int(bw*0.3333)
xh1 = int(bh*0.3333)
xw2 = int(bw*0.6666)
new_im_1 = self.resizeImage(ims[0],xw1,xh1)
new_im_2 = self.resizeImage(ims[1],xw1,xh1)
new_im_3 = self.resizeImage(ims[2],xw1,xh1)
new_im_4 = self.resizeImage(ims[3],xw1,xh1)
new_im_5 = self.resizeImage(ims[4],xw1,xh1)
new_im_6 = self.resizeImage(ims[5],xw1,xh1)
new_im_7 = self.resizeImage(ims[6],xw1,xh1)
new_im_8 = self.resizeImage(ims[7],xw2,xh1)
ft.paste(new_im_1, (-lineW, -lineW))
ft.paste(new_im_2, (xw1+lineW, -lineW))
ft.paste(new_im_3, ((xw1+lineW)*2, -lineW))
ft.paste(new_im_4, (-lineW, xh1))
ft.paste(new_im_5, (xw1+lineW, xh1))
ft.paste(new_im_6, ((xw1+lineW)*2, xh1))
ft.paste(new_im_7, (-lineW, (xh1+lineW)*2))
ft.paste(new_im_8, (xw1+lineW, (xh1+lineW)*2))
pass
实现标题遮罩效果
预览
代码实现逻辑
def combineTextImages(self,im):
width = im.size[0]
height = im.size[1]
fontSize = 60
#生成一张空白图像
imgCircle = Image.new("RGBA",(width,height))
ft = ImageFont.truetype("./font/SYHT.TTF", fontSize)
scale = 0.8
img_w = int(width*scale)
img_h = int(height*scale)
# 缩放遮罩圆
imgCircle = imgCircle.resize( (width,height) )
draw = ImageDraw.Draw(imgCircle)
draw.chord(( int((width-img_w)*0.5), int((height-img_h)*0.5), img_w+int((width-img_w)*0.5), img_h+int((height-img_h)*0.5) ), 0, 360, fill=(0,0,0,150))
w = int((width-img_w)*0.5)
h = int((height-img_h)*0.5)
#绘制横条标题栏
# imgRect = Image.new( "RGBA", (width, height) )
# drawRect = ImageDraw.Draw(imgRect)
txt = "水彩手绘花卉花朵植物卡片" #标题信息
txt = txt[0:28]
txt1 = ''
txt2 = ''
if(len(txt) > 14):
txt1 = txt[0:13]
txt2 = txt[13:]
else:
txt1 = txt
# 如果两行
if(txt2 != ''):
txt1_len = self.calcTxtLen(txt1)*fontSize
txt2_len = self.calcTxtLen(txt2)*fontSize
draw.text( (int((width-txt1_len)/2), int(height*0.375+height*0.25*0.3)-fontSize), u''+txt1, font = ft, fill = '#ffffff')
draw.text( (int((width-txt2_len)/2), int(height*0.375+height*0.25*0.8)-fontSize), u''+txt2, font = ft, fill = '#ffffff')
pass
# 如果一行
else:
txt_len = self.calcTxtLen(txt1)*fontSize
print(txt_len)
draw.text( (int((width-txt_len)/2), int(height*0.375+height*0.25*0.6)-fontSize), u''+txt1, font = ft, fill = '#ffffff') #int((width-txt_len)/2),int(height*0.375+height*0.25*0.4) - fontSize)
pass
# 开始半透明素材
im.paste(imgCircle, ( 0, 0 ), mask=imgCircle)
im.show()
im.save('xxx.png')
im.close()
pass
根据自定义形状裁剪框合理裁剪任意大小图片逻辑
# 尺寸重新缩放
def resizeImage(self, im, w, h):
#im = Image.open(path,"r")
im = im
# 获取图片尺寸
size_w = im.size[0]
size_h = im.size[1]
# 判断是竖着图还是横着的图
resize_w = 0
resize_h = 0
# 获取原素材的缩放倍数
resize = self.calcWH(w,h,size_w,size_h)
im = im.resize((resize[0],resize[1]))
# 获取裁剪的位置x1,y1,x2,y2
box_pos = self.calcCropPos(w,h,resize[0],resize[1])
box = [box_pos[0],box_pos[1],box_pos[2],box_pos[3]]
im = im.crop(box)
return im
#计算宽高比例
def calcWH(self, w1, h1, w2, h2):
resize_w = 0
resize_h = 0
# 横图
if(w1 >= h1):
wh_1 = h1/w1
wh_2 = h2/w2
# 按宽计量
if(wh_1 < wh_2):
resize_w = w1
resize_h = int(w1/w2*h2)
# 按高计量
else:
resize_w = int(h1/h2*w2)
resize_h = h1
# 竖图
else:
wh_1 = w1/h1
wh_2 = w2/h2
# 按宽计量
if(wh_1 < wh_2):
resize_w = int(h1/h2*w2)
resize_h = h1
# 按高计量
else:
resize_w = w1
resize_h = int(w1/w2*h2)
return (resize_w, resize_h)
# 计算裁剪的位置坐标
def calcCropPos(self, w1, h1, w2, h2):
x1 = 0
y1 = 0
x2 = 0
y2 = 0
if(w1 == w1):
x1 = 0
y1 = int((h2-h1)*0.5)
x2 = w1
y2 = int((h2-h1)*0.5)+h1
else:
x1 = int((w2-w1)*0.5)
y1 = 0
x2 = int((w2-w1)*0.5)+w1
y2 = h1
return (x1, y1, x2, y2)