从图像列表创建PDF


72

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

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

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

我需要执行与此非常相似的操作,但是要使用Python。我知道pyPdf模块,但是我想要一些简单的东西。

@编辑

如果您是通过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")

7
您可以从问题中删除答案部分并将其正确发布为单独的答案吗?
Jongware '17

还是PIL第三包?我无法使用安装它pip install PIL
拉维·钱德拉

1
@RaviChandraPIL是已停产的软件包。Pillow是一个PIL分支和活动项目。
macabeus

1
如果图像尺寸不同怎么办?
Palak

Answers:


70

为Python安装FPDF

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")

您可以在教程页面官方文档中找到更多信息。


1
谢谢,但我没有成功。我正在处理的图像是JPG;FDPF不支持JPG。为此,需要PIL。由于PIL不再支持Python 3,因此我安装了PILLOW。但是,FDPF显然无法识别:“未安装PIL”。出于测试目的,我使用PNG图像进行了测试,但是会导致以下错误:“不是PNG文件:0.png”
macabeus 2014年

@KeplerBR在我的回答中,上面我已经使用了pgmagick' which supports jpg,png,JPEG 2000`和许多其他格式,并且图像到pdf转换的效果也很好。
Tanveer Alam 2014年

16
对于A4大小的分页pdf,w和h的值分别为210和297。
GiriB '16

3
我用这种方法遇到的问题是,由于某种原因,每隔一页都是空白的。
nimdil

5
你能说出x,y,w和h的值是多少吗?
Prajwal

43

到目前为止,我尝试过的将多个图像转换为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为要添加的图像列表。Trueappend_images

您可能会遇到AttributeError: 'JpegImageFile' object has no attribute 'encoderinfo'。解决方案在这里将多个JPEG保存为多页PDF时出错

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


2
最好的方法,直接用PIL!
巴斯基

34

如果您使用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")]))

(如果由于路径问题而使用先前的方法遇到任何错误)

# convert all files matching a glob
import glob
with open("name.pdf","wb") as f:
    f.write(img2pdf.convert(glob.glob("/path/to/*.jpg")))

我无法使用字符串指定目录。我必须先使用更改目录,os.chdir('path')然后[i for i in os.listdir(os.getcwd()) if i.endswith(".jpg")]
Stu

4
TypeError:既未实现read(),也未实现str或bytes给出此错误
Palak

5

pgmagickGraphicsMagick(Magick++)Python的绑定。

这是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:

在此处输入图片说明

PDF looks like this:

在此处输入图片说明

Windows的pgmagick iinstallation指示:

1)从非官方Windows二进制文件(适用于Python扩展程序包)下载预编译的二进制程序(如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)然后您可以按照此处的安装说明进行操作。

pip install pgmagick

然后尝试导入它。

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

我看到了您的答案,但是无法安装ImageMagick。当我尝试安装模块时,总是收到错误消息“找不到Magick ++”。我尝试通过二进制文件安装。似乎已成功安装,但似乎没有生效。我真的需要安装源代码吗?还是我出了什么问题?
macabeus 2014年

@KeplerBR您使用的是哪个操作系统?是的,我知道Magic ++是安装pgmagick所必需的依赖项,但值得,因为在很多情况下它都很棒。
Tanveer Alam 2014年

1
@KeplerBR参见上文,我添加了pgmagick的Windows安装说明。
Tanveer Alam 2014年

我看到了lfd页面,但是,我使用的是python 3.4,它最多支持3.2。我无法成功编译源代码。否则,否则我必须编译?
macabeus 2014年

您应该尝试使其复杂化,或者以其他明智的方式切换回Python 3.2也是一种选择。
Tanveer Alam 2014年

3
**** 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")

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")

2

如果图像是您通过matplotlib创建的图,则可以使用matplotlib.backends.backend_pdf.PdfPages请参阅文档)。

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()

PDFPages是一个python非常有效的稀有图书馆
StephenBoesch

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)

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)

1

这不是一个真正的新答案,但是-使用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 ))

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];

我试图通过传递不同的resolution值(如其他答案中所建议的)来更改文件大小,但无济于事。该quality参数的伎俩。
Tonechas

是的,我有同样的问题。
faysou

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)

0

我遇到了同样的问题,因此我创建了一个python函数,以将多个图片合并为一个pdf。该代码(可从我的github页面获取,使用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)

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

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以外,什么都不需要:)


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。但是在这里我已经根据我的图像调整了高度。或者,您可以使用保持纵横比(如我在上面所述)来适当缩放图像的宽度和高度。


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)

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))
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.