从图像列表创建 PDF

Posted

技术标签:

【中文标题】从图像列表创建 PDF【英文标题】:Create PDF from a list of images 【发布时间】:2015-02-04 07:25:24 【问题描述】:

有没有任何实用的方法可以使用 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 模块,但我想要一些简单的东西。

【问题讨论】:

您能否从问题中删除答案部分并正确发布,作为单独的答案? PIL 也是第三个包吗?我无法使用pip install PIL 安装它。 @RaviChandra PIL 是一个已停产的软件包。 Pillow 是一个 PIL 分支和活跃项目。 图片大小不同怎么办? 【参考方案1】:

安装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 page 或official documentation。

【讨论】:

谢谢,但我无法成功。我正在处理的图像是 JPG; FDPF 没有对 JPG 的原生支持。为此,需要 PIL。由于 PIL 不再支持 Python 3,因此我安装了 PILLOW。但是,FDPF 显然无法识别:“PIL 未安装”。出于测试目的,我使用 PNG 图像进行了测试,但是,导致以下错误:“Not a PNG file: 0.png” 对于 A4 尺寸的分页 PDF,w 和 h 的值分别为 210 和 297。 我使用这种方法遇到的问题是,由于某种原因,每隔一页都是空白的。 你能说出 x,y,w 和 h 的值是什么吗? 对于标准 (a4) 页面,x,y,w,h 的值应该是多少?编辑:看起来像 0,0,210,297 作品【参考方案2】:

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:

PDF looks like this:

pgmagick iinstallation for windows:

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'
>>>

【讨论】:

我看到了你的回答,但我无法安装 ImageMagick。当我尝试安装模块时,总是收到错误消息“Magick ++ not found”。我尝试通过二进制文件安装。好像已经安装成功了,但是好像没有生效。我真的需要通过源安装吗?还是我做错了什么? @KeplerBR 您使用的是哪个操作系统?是的,我知道 Magic++ 是安装 pgmagick 所需的依赖项,但它值得,因为它在许多情况下都很棒。 @KeplerBR 见上文我已经添加了 pgmagick for windows 的安装说明。 我看到了 lfd 页面,但是,我使用的是 python 3.4,它最高支持 3.2。我无法成功编译源代码。否则会有,否则我必须编译? 你应该尝试编译它或其他明智的切换回 Python 3.2 也是一种选择。【参考方案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")

【讨论】:

【参考方案4】:

从文件所在的目录制作 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)

【讨论】:

【参考方案5】:

如果你使用 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")] TypeError: 既不实现 read() 也不实现 str 或 bytes 给出此错误【参考方案6】:

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

Create PDF from a list of images Combining multiple pngs in a single pdf in python png images to one pdf in python How can I convert all JPG files in a folder to PDFs and combine them? https://www.blog.pythonlibrary.org/2012/01/07/reportlab-converting-hundreds-of-images-into-pdfs/

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

我们有包含 png 和 jpg 类型图片的文件夹“D:\pictures”,我们想从中创建文件 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)

【讨论】:

【参考方案7】:

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

【讨论】:

最佳方法,直接使用 PIL! 这种方法对我有用。 最佳答案。这也比 ilya-vinnichenko 的答案快 2 倍左右,即循环所有图像并一张一张地添加到 pdf 中。【参考方案8】:
**** 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")

【讨论】:

【参考方案9】:

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

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)

【讨论】:

【参考方案10】:

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

【讨论】:

【参考方案11】:

如果您的图像是您在 matplotlib 中创建的图,您可以使用 matplotlib.backends.backend_pdf.PdfPages (See 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()

【讨论】:

PDFPages 是一个罕见的 python 库,真的很好用【参考方案12】:

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

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】:

这是 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 参数起到了作用。 是的,我遇到了同样的问题。【参考方案14】:

受@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 什么都不需要 :)

【讨论】:

【参考方案15】:

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

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”纸的尺寸,横向宽度为 297 毫米,高度为 210 毫米;但在这里我已经根据我的图像调整了高度。或者,您可以使用我上面评论的保持纵横比来正确缩放图像的宽度和高度。

【讨论】:

【参考方案16】:

命令行界面中的第一个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)

【讨论】:

【参考方案17】:

我知道这是一个老问题。就我而言,我使用 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)。可以通过宽度和高度参数来缩小或放大图像以指示其尺寸。

以下代码提供了 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)

【讨论】:

【参考方案18】:

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

【讨论】:

【参考方案19】:

您可以使用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

【讨论】:

【参考方案20】:

添加到@ilovecomputer 的答案,如果您想将 pdf 保存在内存中而不是磁盘中,那么您可以这样做:

import io
from pdf2image import convert_from_bytes
 
pil_images = convert_from_bytes(original_pdf_bytes, dpi=100) # (OPTIONAL) do this if you're converting a normal pdf to images first and then back to only image pdf
pdf_output = io.BytesIO()
pil_images[0].save(pdf_output, "PDF", resolution=100.0, save_all=True, append_images=pil_images[1:])
pdf_bytes = pdf_output.getvalue()

【讨论】:

以上是关于从图像列表创建 PDF的主要内容,如果未能解决你的问题,请参考以下文章

如何使用图像的 tesseract 输出从另一个图像创建可搜索的 pdf

如何从使用 pdfkit 相机拍摄的图像创建 pdf

使用 Ghostscript 从单个 JPG 文件创建 PDF - PDF 中的图像放置问题

如何从 Python 创建 PDF 文件,包括图像和文本? [关闭]

在创建 pdf 时,图像未在 Flutter 中显示

R语言可视化绘制及PDF使用字体参数列表:查看字体列表可视化绘制图像中的字体参数列表字体示例并写入pdf