Python批量将多张图片拼接为PDF

最近碰到一个问题,想要把一个文件夹下的图片拼接起来生成一个PDF文件,并且该PDF文件每页都具有相同的A4大小。其实生成PDF这件事有许多方法可以办到,最简单可以用word或者acrobat,然而通过这些软件来生成PDF文件有些问题无法避免,一是样式无法自定义,二是不太好把它做成一个模块嵌入到其他需要使用的地方。于是就想能否自己来写,好在Python轮子多,简单搜索了一下,用ReportLab似乎可以达到自己的要求。

实现方法

代码实现起来倒是不复杂,但是有一点需要注意,那就是用PIL打开一个图片的时候,当它是JPEG格式的时候,我发现它总是旋转过的,因此我们需要读取一下该图片的exif信息,将它转过来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def rotate_img_to_proper(image):
try:
if hasattr(image, '_getexif'): # only present in JPEGs
for orientation in PIL.ExifTags.TAGS.keys():
if PIL.ExifTags.TAGS[orientation] == 'Orientation':
break
e = image._getexif() # returns None if no EXIF data
if e is not None:
#log.info('EXIF data found: %r', e)
exif = dict(e.items())
orientation = exif[orientation]
# print('found, ',orientation)
if orientation == 3:
image = image.transpose(Image.ROTATE_180)
elif orientation == 6:
image = image.transpose(Image.ROTATE_270)
elif orientation == 8:
image = image.rotate(90,expand=True)
except:
pass
return image

随后我们就可以将图片保持长宽比地resize到A4页面中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# new a Doc
imgDoc = canvas.Canvas(output_file_name)#pagesize=letter
imgDoc.setPageSize(A4)
document_width,document_height = A4
# fill each page with a image
image_file = PIL.Image.open(image)
image_file = rotate_img_to_proper(image_file)
image_width,image_height = image_file.size
if not(image_width>0 and image_height>0):
raise Exception
image_aspect = image_height/float(image_width)
#Determins the demensions of the image in the overview
print_width = document_width
print_height = document_width*image_aspect
imgDoc.drawImage(ImageReader(image_file),document_width-print_width,
document_height-print_height,width=print_width,
height=print_height,preserveAspectRatio=True)
#inform the reportlab we want a new page
imgDoc.showPage()
imgDoc.save()

结果

最终拼接出来的结果,是这个样子的
result
完整的代码放在Github上,可以根据需求稍加更改使用