对于一些零散的图片,想要把它们给拼接起来,有时候呢,再把它转化为PDF格式可能会更方便一点,那么接下来讲的可能就会派上用场。
没错,如标题所说,就一个库,PIL,就能实现这些功能【完整代码在文章最后】
当然整个过程还得依靠一下其他库来获取下文件,或者实现一些其它小操作
-
首先,把需要拼接的图片保存到一个文件夹,保证该文件下除了需要的文件外没有其他图片文件。
-
还有,要保证图片按名称排列的次序和拼接顺序一致(也不一定非这样,不这样的话,就需要写额外代码排序),而一般保存的时候一系列的图片的名称已经是有序的了,所以就先这么来吧。
path = r'c:\users\...\...'
imgs = [op.join(path, name) for name in os.listdir(path)]
不难发现,这获取到的不仅是文件夹下的图片路径,而是该文件下所有的文件路径, 没关系,后面可以通过试错来给它筛喽(当然也可以多写几行代码筛选一下,保留住图片的文件路径[依据后缀],甚至筛选出一些特定的图片文件)
hight = 20 + 5*len(img_list)
for im in imgs:
try:
img = Image.open(im).convert('RGB')
img_list.append(img)
if if_parse:
size_list.append(list(img.size))
hight += img.size[1]
except:
pass
try 的使用,就不用怕遍历打开路径的时候遇到非图片而报错停止了
size_lt = sorted(size_list, key=lambda x: x[0])
width = size_lt[-1][0] + 10
canv = Image.new('RGB', (width, hight), (255, 255, 255))
然后就可以遍历贴图了
先获取当前要贴的图片的尺寸,然后用画布宽度减去图片宽度最后整除2得到贴图时左上角坐标,使得图片位置居中
y = 10 # 10 为上边的留白值
for i in range(len(img_list)):
size = size_list[i]
dx = (width - size[0])//2
canv.paste(img_list[i], (dx, y))
y 为每次贴图的 ‘纵’ 坐标,每次贴图后要加上所贴图的高度以及留白值 5, 得到下一次贴图的 ‘纵’ 坐标
y = 10
for i in range(len(img_list)):
size = size_list[i]
dx = (width - size[0]) // 2
canv.paste(img_list[i], (dx, y))
img_list[i].close() # 用完就顺手关闭一下图片
y += size[1] + 5
canv = Image.new('RGB', \
(10 + img_list[0].size[0], 20 + len(img_list)*(img_list[0].size[1] + 5)), (255, 255, 255))
接下来就是没有感情的贴图
for i in range(len(img_list)):
canv.paste(img_list[i], (5, 10 + i * (5 + img_list[0].size[1])))
img_list[i].close()
draw = ImageDraw.Draw(canv)
draw.rectangle((0, 0, canv.size[0]-1, canv.size[1]-1), outline='black', width=5)
第一个元组参数,前两个是框框左上角的坐标,后两个是框框右下角的坐标
outline 是框框的颜色; width 是框框的宽度
弄完这些,保存一下吧
canv.save(out_path, 'PDF', resolution=100.0, save_all=True)
Ps: 要是不需要拼长图,而是需要一张图,一页pdf,那么就改一下保存的代码。
img_list[0].save(out.path, "PDF", resolution=100.0, save_all=True, append_images=img_list[1:])
这里解释一下,img_list 是Image对象的列表。另,这样的话,效果如下
完整代码如下
from PIL import Image, ImageDraw
from random import randint
import os.path as op
import os
def paste_and_pdf(path, show=True, if_parse=None, out_path=r'c:\users\pxo\desktop\document_{}.pdf'.format(randint(0, 999))):
while op.exists(out_path):
out_path = r'c:\users\pxo\desktop\document_{}.pdf'.format(randint(0, 999))
imgs = [op.join(path, name) for name in os.listdir(path)]
size_list, img_list = [], []
hight = 20 + 5*len(img_list)
for im in imgs:
try:
img = Image.open(im).convert('RGB')
img_list.append(img)
if if_parse:
size_list.append(list(img.size))
hight += img.size[1]
except:
pass
if if_parse:
size_lt = sorted(size_list, key=lambda x: x[0])
width = size_lt[-1][0] + 10
canv = Image.new('RGB', (width, hight), (255, 255, 255))
y = 10
for i in range(len(img_list)):
size = size_list[i]
dx = (width - size[0])//2
canv.paste(img_list[i], (dx, y))
img_list[i].close()
y += size[1]+5
else:
canv = Image.new('RGB', (10 + img_list[0].size[0], 20 + len(img_list)*(img_list[0].size[1] + 5)), (255, 255, 255))
for i in range(len(img_list)):
canv.paste(img_list[i], (5, 10 + i*(5+img_list[0].size[1])))
img_list[i].close()
draw = ImageDraw.Draw(canv)
draw.rectangle((0, 0, canv.size[0]-1, canv.size[1]-1), outline='black', width=5)
canv.save(out_path, 'PDF', resolution=100.0, save_all=True)
if show:
canv.show()
def old_paste_pic():
# im1.save(pdf_name, "PDF", resolution=100.0, save_all=True, append_images=im_list)
path = r'c:\users\pxo\desktop\tt'
imgs = [op.join(path, name) for name in os.listdir(path)]
size = Image.open(imgs[0]).size
new = Image.new('RGB', (size[0], size[1]*len(imgs)))
for i in range(len(imgs)):
im = Image.open(imgs[i])
new.paste(im, (0, size[1]*i))
new.show()
new.save(op.join(path, 'new.jpeg'), quality=90)
def main():
path = r'c:\users\pxo\desktop\ttt'
out_path = op.join(path, 'out.pdf')
paste_and_pdf(path, if_parse=1, out_path=out_path)
main()