从图像列表中创建PDF

时间:2014-12-06 02:04:23

标签: python pdf

是否有任何实用的方法可以使用Python从图像文件列表创建PDF?

在Perl中,我知道that module。有了它,我可以只用3行创建一个PDF:

use PDF::FromImage;
...
my $pdf = PDF::FromImage->new;
$pdf->load_images(@allPagesDir);
$pdf->write_file($bookName . '.pdf');

我需要做一些与此类似的事情,但是在Python中。我知道pyPdf模块,但我想要一些简单的东西。

@Edit

如果您通过Google访问,请输入以下代码:

from fpdf import FPDF
from PIL import Image
def makePdf(pdfFileName, listPages, dir = ''):
    if (dir):
        dir += "/"

    cover = Image.open(dir + str(listPages[0]) + ".jpg")
    width, height = cover.size

    pdf = FPDF(unit = "pt", format = [width, height])

    for page in listPages:
        pdf.add_page()
        pdf.image(dir + str(page) + ".jpg", 0, 0)

    pdf.output(dir + pdfFileName + ".pdf", "F")

19 个答案:

答案 0 :(得分:43)

安装FPDF for Python

pip install fpdf

现在你可以使用相同的逻辑:

from fpdf import FPDF
pdf = FPDF()
# imagelist is the list with all image filenames
for image in imagelist:
    pdf.add_page()
    pdf.image(image,x,y,w,h)
pdf.output("yourfile.pdf", "F")

您可以找到更多信息at the tutorial pageofficial documentation

答案 1 :(得分:19)

如果使用Python 3,则可以使用python模块img2pdf

使用pip3 install img2pdf安装它,然后您可以在脚本中使用它 使用import img2pdf

示例代码

import os
import img2pdf

with open("output.pdf", "wb") as f:
    f.write(img2pdf.convert([i for i in os.listdir('path/to/imageDir') if i.endswith(".jpg")]))

答案 2 :(得分:14)

将多个图像转换为PDF的最佳方法我到目前为止尝试过纯粹使用PIL。它非常简单但功能强大:

from PIL import Image

im1 = Image.open("/Users/apple/Desktop/bbd.jpg")
im2 = Image.open("/Users/apple/Desktop/bbd1.jpg")
im3 = Image.open("/Users/apple/Desktop/bbd2.jpg")
im_list = [im2,im3]

pdf1_filename = "/Users/apple/Desktop/bbd1.pdf"

im1.save(pdf1_filename, "PDF" ,resolution=100.0, save_all=True, append_images=im_list)

只需将save_all设置为True,将append_images设置为您要添加的图片列表。

您可能会遇到AttributeError: 'JpegImageFile' object has no attribute 'encoderinfo'。解决方案在Error while saving multiple JPEGs as a multi-page PDF

注意:安装最新的PIL以确保save_all参数可用于PDF。

答案 3 :(得分:3)

pgmagick是Python的GraphicsMagick(Magick++)绑定。

它是ImageMagick(或GraphicsMagick)的Python包装器。

import os
from os import listdir
from os.path import isfile, join 
from pgmagick import Image

mypath = "\Images" # path to your Image directory 

for each_file in listdir(mypath):
    if isfile(join(mypath,each_file)):
        image_path = os.path.join(mypath,each_file)
        pdf_path =  os.path.join(mypath,each_file.rsplit('.', 1)[0]+'.pdf')
        img = Image(image_path)
        img.write(pdf_path)

Sample input Image:

enter image description here

PDF looks like this:

enter image description here

用于windows的pgmagick iinstallation指令:

1)从Unofficial Windows Binaries for Python Extension Packages下载预编译的二进制包(如pgmagick网页中所述)并安装它。

注意: 尝试下载与您机器中安装的python版本对应的正确版本,无论是32位安装还是64位。

只需在终端输入python并按Enter即可检查是否有32位或64位python。

D:\>python
ActivePython 2.7.2.5 (ActiveState Software Inc.) based on
Python 2.7.2 (default, Jun 24 2011, 12:21:10) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.

因此它有python version 2.7及其32 bit (Intel)] on win32所以你必须下载并安装pgmagick‑0.5.8.win32‑py2.7.exe

以下是pgmagick的可用Python扩展包:

  • pgmagick-0.5.8.win-AMD64的py2.6.exe
  • pgmagick-0.5.8.win-AMD64的py2.7.exe
  • pgmagick-0.5.8.win-AMD64的py3.2.exe
  • pgmagick-0.5.8.win32-py2.6.exe
  • pgmagick-0.5.8.win32-py2.7.exe
  • pgmagick-0.5.8.win32-py3.2.exe

2)然后您可以按照here的安装说明进行操作。

pip install pgmagick

然后尝试导入它。

>>> from pgmagick import gminfo
>>> gminfo.version
'1.3.x'
>>> gminfo.library
'GraphicsMagick'
>>>

答案 4 :(得分:3)

这个怎么样?

from fpdf import FPDF
from PIL import Image
import glob
import os


# set here
image_directory = '/path/to/imageDir'
extensions = ('*.jpg','*.png','*.gif') #add your image extentions
# set 0 if you want to fit pdf to image
# unit : pt
margin = 10

imagelist=[]
for ext in extensions:
    imagelist.extend(glob.glob(os.path.join(image_directory,ext)))

for imagePath in imagelist:
    cover = Image.open(imagePath)
    width, height = cover.size

pdf = FPDF(unit="pt", format=[width + 2*margin, height + 2*margin])
pdf.add_page()

pdf.image(imagePath, margin, margin)

destination = os.path.splitext(imagePath)[0]
pdf.output(destination + ".pdf", "F")

答案 5 :(得分:2)

命令行界面中的第一个pip install pillow。 图片可以是jpg或png格式。如果您有2张或更多图片,并且想要制作1张pdf文件。

代码:

from PIL import Image

image1 = Image.open(r'locationOfImage1\\Image1.png')
image2 = Image.open(r'locationOfImage2\\Image2.png')
image3 = Image.open(r'locationOfImage3\\Image3.png')

im1 = image1.convert('RGB')
im2 = image2.convert('RGB')
im3 = image3.convert('RGB')

imagelist = [im2,im3]

im1.save(r'locationWherePDFWillBeSaved\\CombinedPDF.pdf',save_all=True, append_images=imagelist)

答案 6 :(得分:2)

**** Convert images files to pdf file.****
from os import listdir
from fpdf import FPDF

path = "/home/bunny/images/" # get the path of images

imagelist = listdir(path) # get list of all images

pdf = FPDF('P','mm','A4') # create an A4-size pdf document 

x,y,w,h = 0,0,200,250

for image in imagelist:

    pdf.add_page()
    pdf.image(path+image,x,y,w,h)

pdf.output("images.pdf","F")

答案 7 :(得分:2)

如果图像是您通过matplotlib创建的图,则可以使用matplotlib.backends.backend_pdf.PdfPagesSee documentation)。

import matplotlib.pyplot as plt
from matplotlib.backends.backend_pdf import PdfPages

# generate a list with dummy plots   
figs = []
for i in [-1, 1]:
    fig = plt.figure()
    plt.plot([1, 2, 3], [i*1, i*2, i*3])
    figs.append(fig)

# gerate a multipage pdf:
with PdfPages('multipage_pdf.pdf') as pdf:
    for fig in figs:
        pdf.savefig(fig)
        plt.close()

答案 8 :(得分:1)

您可以使用 pdfme。是python中创建PDF文档最强大的库。

from pdfme import build_pdf

...

pdf_image_list = [{"image": img} for img in images]

with open('images.pdf', 'wb') as f:
    build_pdf({"sections": [{"content": pdf_image_list}]})

检查文档 here

答案 9 :(得分:1)

这是ilovecomputer的答案,打包成一个函数,可以直接使用。它还可以减小图像尺寸,并且效果很好。

该代码假定input_dir中有一个文件夹,其中包含按图像名称按字母顺序排序的图像,并输出带有该文件夹名称的pdf文件,并可能以该名称为前缀字符串。

import os
from PIL import Image

def convert_images_to_pdf(export_dir, input_dir, folder, prefix='', quality=20):
    current_dir = os.path.join(input_dir, folder)
    image_files = os.listdir(current_dir)
    im_list = [Image.open(os.path.join(current_dir, image_file)) for image_file in image_files]

    pdf_filename = os.path.join(export_dir, prefix + folder + '.pdf')
    im_list[0].save(pdf_filename, "PDF", quality=quality, optimize=True, save_all=True, append_images=im_list[1:])

export_dir = r"D:\pdfs"
input_dir = r"D:\image_folders"
folders = os.listdir(input_dir)
[convert_images_to_pdf(export_dir, input_dir, folder, prefix='') for folder in folders];

答案 10 :(得分:1)

我知道这个问题已经得到解答,但解决这个问题的另一种方法是使用枕头库。 要转换整个图像目录:

from PIL import Image
import os


def makePdf(imageDir, SaveToDir):
     '''
        imageDir: Directory of your images
        SaveToDir: Location Directory for your pdfs
    '''
    os.chdir(imageDir)
    try:
        for j in os.listdir(os.getcwd()):
            os.chdir(imageDir)
            fname, fext = os.path.splitext(j)
            newfilename = fname + ".pdf"
            im = Image.open(fname + fext)
            if im.mode == "RGBA":
                im = im.convert("RGB")
            os.chdir(SaveToDir)
            if not os.path.exists(newfilename):
                im.save(newfilename, "PDF", resolution=100.0)
    except Exception as e:
        print(e)

imageDir = r'____' # your imagedirectory path
SaveToDir = r'____' # diretory in which you want to save the pdfs
makePdf(imageDir, SaveToDir)

在单张图片上使用它:

From PIL import Image
import os

filename = r"/Desktop/document/dog.png"
im = Image.open(filename)
if im.mode == "RGBA":
    im = im.convert("RGB")
new_filename = r"/Desktop/document/dog.pdf"
if not os.path.exists(new_filename):
    im.save(new_filename,"PDF",resolution=100.0)

答案 11 :(得分:0)

这不是一个真正的新答案,但是-使用img2pdf时,页面大小显示不正确。所以这是我使用图像尺寸的方法,希望它能找到合适的人:

假设1)所有图像的尺寸相同,2)每页放置一张图像,3)图像充满整个页面

from PIL import Image
import img2pdf

with open( 'output.pdf', 'wb' ) as f:
    img = Image.open( '1.jpg' )
    my_layout_fun = img2pdf.get_layout_fun(
        pagesize = ( img2pdf.px_to_pt( img.width, 96 ), img2pdf.px_to_pt( img.height, 96 ) ), # this is where image size is used; 96 is dpi value
        fit = img2pdf.FitMode.into # I didn't have to specify this, but just in case...
    )
    f.write( img2pdf.convert( [ '1.jpg', '2.jpg', '3.jpg' ], layout_fun = my_layout_fun ))

答案 12 :(得分:0)

最佳答案已经存在!!!我只是在稍微改善答案。 这是代码:

from fpdf import FPDF
pdf = FPDF()
# imagelist is the list with all image filenames you can create using os module by iterating all the files in a folder or by specifying their name
for image in imagelist:
    pdf.add_page()
    pdf.image(image,x=0,y=0,w=210,h=297) # for A4 size because some people said that every other page is blank
pdf.output("yourfile.pdf", "F")

为此,您需要安装FPDF。

pip install FPDF

答案 13 :(得分:0)

受@ilovecomputer的回答启发,现成的解决方案可将当前文件夹中的所有PNG转换为PDF。

import glob, PIL.Image
L = [PIL.Image.open(f) for f in glob.glob('*.png')]
L[0].save('out.pdf', "PDF" ,resolution=100.0, save_all=True, append_images=L[1:])

除了PIL之外,什么都不需要:)

答案 14 :(得分:0)

如果图像处于横向模式,则可以这样做。

from fpdf import FPDF
import os, sys, glob
from tqdm import tqdm

pdf = FPDF('L', 'mm', 'A4')
im_width = 1920
im_height = 1080

aspect_ratio = im_height/im_width
page_width = 297
# page_height = aspect_ratio * page_width
page_height = 200
left_margin = 0
right_margin = 0

# imagelist is the list with all image filenames
for image in tqdm(sorted(glob.glob('test_images/*.png'))):
pdf.add_page()
pdf.image(image, left_margin, right_margin, page_width, page_height)
pdf.output("mypdf.pdf", "F")
print('Conversion completed!')

这里的page_width和page_height是'A4'纸的尺寸,在横向中其宽度为297mm,高度为210mm;但是在这里我已经根据我的图像调整了高度。或者,您可以使用保持上面所述的高宽比来适当缩放图像的宽度和高度。

答案 15 :(得分:0)

我遇到了同样的问题,所以我创建了一个python函数来将多个图片合并为一个pdf。该代码(可从my github page获取,使用reportlab,并基于以下链接的答案:

以下是如何将图像合并为pdf的示例:

我们有文件夹“D:\ pictures”和png和jpg类型的图片,我们想要创建文件pdf_with_pictures.pdf并保存在同一个文件夹中。

outputPdfName = "pdf_with_pictures"
pathToSavePdfTo = "D:\\pictures"
pathToPictures = "D:\\pictures"
splitType = "none"
numberOfEntitiesInOnePdf = 1
listWithImagesExtensions = ["png", "jpg"]
picturesAreInRootFolder = True
nameOfPart = "volume"

unite_pictures_into_pdf(outputPdfName, pathToSavePdfTo, pathToPictures, splitType, numberOfEntitiesInOnePdf, listWithImagesExtensions, picturesAreInRootFolder, nameOfPart)

答案 16 :(得分:0)

我知道这是一个老问题。就我而言,我使用Reportlab。

纸页尺寸以点而不是像素表示,其点等于1/72英寸。 A4纸由595.2点宽和841.8点高组成。位置坐标(0,0)的原点在左下角。创建canvas.Canvas实例时,可以使用pagesize参数指定图纸的大小,并传递一个元组,其第一个元素表示以磅为单位的宽度,第二个元素表示以磅为单位的高度。 c.showPage()方法告诉ReportLab它已经完成了对当前工作表的处理,并移至下一个工作表。尽管尚未处理第二张纸(只要未绘制任何内容,第二张纸就不会出现在文档中),但最好记住在调用c.save()之前先这样做。要将图像插入PDF文档中,ReportLab使用Pillow库。 drawImage()方法将图像的路径(支持多种格式,例如PNG,JPEG和GIF)和要插入的位置(x,y)作为其参数。可以通过width和height参数来缩小或放大图像以指示其尺寸。

以下代码提供了pdf文件名,带有png文件的列表,用于插入图像的坐标以及适合纵向字母页面的大小。

def pntopd(file, figs, x, y, wi, he):
    from reportlab.pdfgen import canvas
    from reportlab.lib.pagesizes import A4, letter, landscape, portrait
    w, h = letter
    c = canvas.Canvas(str(file), pagesize=portrait(letter))
    for png in figs:
        c.drawImage(png, x, h - y, width=wi, height=he)
        c.showPage()
    c.save()
    
    
    
from datetime import date
from pathlib import Path
ruta = "C:/SQLite"
today = date.today()
dat_dir = Path(ruta)
tit = today.strftime("%y%m%d") + '_ParameterAudit'
pdf_file = tit + ".pdf"
pdf_path = dat_dir / pdf_file
pnglist = ['C0.png', 'C4387.png', 'C9712.png', 'C9685.png', 'C4364.png']
pntopd(pdf_path, pnglist, 50, 550, 500, 500)

答案 17 :(得分:0)

在python 3.7和img2pdf 0.4.0版中对我有用的是使用类似于Syed Shamikh Shabbir给出的代码的东西,但是按照Stu在对Syed解决方案的评论中建议的那样,使用OS更改当前工作目录

import os
import img2pdf

path = './path/to/folder'
os.chdir(path)
images = [i for i in os.listdir(os.getcwd()) if i.endswith(".jpg")]

for image in images:
    with open(image[:-4] + ".pdf", "wb") as f:
        f.write(img2pdf.convert(image))

值得一提的是,上述解决方案将每个.jpg文件分别保存为一个pdf文件。如果您只希望将所有.jpg文件集中在一个.pdf文件中,则可以执行以下操作:

import os
import img2pdf

path = './path/to/folder'
os.chdir(path)
images = [i for i in os.listdir(os.getcwd()) if i.endswith(".jpg")]

with open("output.pdf", "wb") as f:
    f.write(img2pdf.convert(images))

答案 18 :(得分:0)

从文件

的目录创建pdf的一些更改

我接受了代码并进行了一些细微的改动,使其可用。

from fpdf import FPDF
from PIL import Image
import os # I added this and the code at the end

def makePdf(pdfFileName, listPages, dir=''):
    if (dir):
        dir += "/"

    cover = Image.open(dir + str(listPages[0]))
    width, height = cover.size

    pdf = FPDF(unit="pt", format=[width, height])

    for page in listPages:
        pdf.add_page()
        pdf.image(dir + str(page), 0, 0)

    pdf.output(dir + pdfFileName + ".pdf", "F")


# this is what I added
x = [f for f in os.listdir() if f.endswith(".jpg")]
y = len(x)

makePdf("file", x)