Erstellen Sie PDF aus einer Liste von Bildern

73

Gibt es eine praktische Möglichkeit, mit Python aus einer Liste von Bilddateien ein PDF zu erstellen?

In Perl kenne ich dieses Modul . Damit kann ich ein PDF in nur 3 Zeilen erstellen:

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

Ich muss etwas sehr Ähnliches tun, aber in Python. Ich kenne das pyPdf- Modul, möchte aber etwas Einfaches.

@Bearbeiten

Wenn Sie über Google gekommen sind, ist hier der Code:

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")
Macabeus
quelle
7
Können Sie den Antwortteil aus Ihrer Frage entfernen und als separate Antwort ordnungsgemäß veröffentlichen?
Jongware
ist PILauch ein drittes Paket? Ich kann es nicht mit installieren pip install PIL.
Ravi Chandra
1
@ RaviChandra PIList ein eingestelltes Paket. Pillowist eine PIL-Gabel und ein aktives Projekt.
Macabeus
1
Was ist, wenn die Bilder unterschiedlich groß sind?
Palak

Antworten:

69

Installieren Sie FPDF für Python :

pip install fpdf

Jetzt können Sie dieselbe Logik verwenden:

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

Weitere Informationen finden Sie auf der Tutorial-Seite oder in der offiziellen Dokumentation .

Ilya Vinnichenko
quelle
1
Danke, aber ich konnte keinen Erfolg haben. Die Bilder, an denen ich arbeite, sind JPG; Die FDPF unterstützt JPG nicht nativ. Benötigen Sie dazu die PIL. Da die PIL Python 3 nicht mehr unterstützt, habe ich PILLOW installiert. Die FDPF erkennt jedoch offenbar nicht: "PIL nicht installiert". Zu Testzwecken habe ich mit PNG-Bildern getestet, was jedoch zu folgendem Fehler führt: "Keine PNG-Datei: 0.png"
macabeus
@KeplerBR Gut oben in meiner Antwort habe ich pgmagick' which supports jpg, png, JPEG 2000` und viele andere Formate verwendet und die Ergebnisse sind auch bei der Konvertierung von Bild zu PDF großartig.
Tanveer Alam
15
Für ausgelagerte PDFs der Größe A4 beträgt der Wert für w und h 210 bzw. 297.
GiriB
3
Das Problem, auf das ich bei diesem Ansatz gestoßen bin, ist, dass jede andere Seite aus irgendeinem Grund leer ist.
Nimdil
5
Können Sie sagen, was die Werte für x, y, w und h sind?
Prajwal
41

Die beste Methode, um mehrere Bilder in PDF zu konvertieren, die ich bisher versucht habe, ist die PILreine Verwendung . Es ist ganz einfach und doch mächtig:

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)

Stellen Sie einfach save_allauf Trueund append_imagesin die Liste der Bilder , die Sie hinzufügen möchten.

Sie könnten auf die stoßen AttributeError: 'JpegImageFile' object has no attribute 'encoderinfo'. Die Lösung ist hier Fehler beim Speichern mehrerer JPEGs als mehrseitiges PDF

Hinweis: Installieren Sie die neueste Version PIL, um sicherzustellen, dass das save_allArgument für PDF verfügbar ist.

ilovecomputer
quelle
2
Beste Methode, direkt mit PIL!
Basj
32

Wenn Sie Python 3 verwenden, können Sie das Python-Modul img2pdf verwenden

Installieren Sie es mit pip3 install img2pdfund dann können Sie es in einem Skript mit verwendenimport img2pdf

Beispielcode

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

oder (Wenn Sie aufgrund eines Pfadproblems einen Fehler beim vorherigen Ansatz erhalten)

# convert all files matching a glob
import glob
with open("name.pdf","wb") as f:
    f.write(img2pdf.convert(glob.glob("/path/to/*.jpg")))
Syed Shamikh Shabbir
quelle
Ich konnte es nicht zum Laufen bringen und das Verzeichnis mit einer Zeichenfolge angeben. Ich musste zuerst das Verzeichnis wechseln mit os.chdir('path')und dann[i for i in os.listdir(os.getcwd()) if i.endswith(".jpg")]
Stu
4
TypeError: Weder implementiert read () noch ist str oder bytes Gibt diesen Fehler
Palak
5

pgmagick ist eineGraphicsMagick(Magick++)Bindung für Python.

Es ist ein Python-Wrapper für ImageMagick (oder GraphicsMagick ).

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:

Geben Sie hier die Bildbeschreibung ein

PDF looks like this:

Geben Sie hier die Bildbeschreibung ein

pgmagick iinstallation Anleitung für Windows:

1) Laden Sie vorkompilierte Binärpakete von den inoffiziellen Windows- Binärdateien für Python-Erweiterungspakete herunter (wie auf der pgmagick-Webseite erwähnt) und installieren Sie sie.

Hinweis: Versuchen Sie, die richtige Version herunterzuladen, die Ihrer auf Ihrem Computer installierten Python-Version und der 32-Bit-Installation oder der 64-Bit-Version entspricht.

Sie können überprüfen, ob Sie 32-Bit- oder 64-Bit-Python haben, indem Sie einfach Python an Ihrem Terminal eingeben und die Eingabetaste drücken.

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.

Also hat es python version 2.7und es ist 32 bit (Intel)] on win32so, dass Sie herunterladen und installieren müssen pgmagick‑0.5.8.win32‑py2.7.exe.

Dies sind die folgenden verfügbaren Python-Erweiterungspakete für pgmagick :

  • 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) Dann können Sie von hier aus den Installationsanweisungen folgen .

pip install pgmagick

Und dann versuchen Sie es zu importieren.

>>> from pgmagick import gminfo
>>> gminfo.version
'1.3.x'
>>> gminfo.library
'GraphicsMagick'
>>>
Tanveer Alam
quelle
Ich habe Ihre Antwort gesehen, kann aber die Installation von ImageMagick nicht durchführen. Wenn ich versuche, das Modul zu installieren, wird immer die Fehlermeldung "Magick ++ nicht gefunden" angezeigt. Ich habe versucht, über die Binärdateien zu installieren. Scheint erfolgreich installiert worden zu sein, scheint aber nicht wirksam zu werden. Muss ich wirklich über die Quelle installieren? Oder habe ich etwas falsch gemacht?
Macabeus
@KeplerBR Welches Betriebssystem verwenden Sie? Ja, ich weiß, dass Magic ++ die Abhängigkeit ist, die für die Installation von pgmagick erforderlich ist, aber es lohnt sich, weil es in vielen Fällen erstaunlich ist.
Tanveer Alam
1
@KeplerBR Siehe oben Ich habe die Installationsanleitung von pgmagick für Windows hinzugefügt.
Tanveer Alam
Ich habe die lfd-Seite gesehen, verwende jedoch Python 3.4 und es unterstützt bis zu 3.2. Ich kann Quelle nicht erfolgreich kompilieren. Es würde anders sein, oder ich muss kompilieren?
Macabeus
Sie sollten versuchen, es zu vervollständigen, oder eine andere Möglichkeit, auf Python 3.2 zurückzuschalten, ist ebenfalls eine Option.
Tanveer Alam
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")
user7384403
quelle
3

Wie wäre es damit??

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")
Daisuke Harada
quelle
2

Wenn es sich bei Ihren Bildern um Diagramme handelt, die Sie mit matplotlib erstellt haben, können Sie diese verwenden matplotlib.backends.backend_pdf.PdfPages( siehe Dokumentation ).

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()
Qaswed
quelle
PDFPagesist eine seltene pythonBibliothek, die wirklich gut funktioniert
StephenBoesch
2

zuerst pip install pillowin der Kommandozeilenschnittstelle. Bilder können im JPG- oder PNG-Format vorliegen. Wenn Sie 2 oder mehr Bilder haben und 1 PDF-Datei erstellen möchten.

Code:

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)
Swati Bohidar
quelle
1

Ich weiß, dass die Frage beantwortet wurde, aber eine weitere Möglichkeit, dies zu lösen, ist die Verwendung der Kissenbibliothek. So konvertieren Sie ein ganzes Verzeichnis von Bildern:

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)

Für die Verwendung auf einem einzelnen Bild:

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)
Vaibhav Singh
quelle
1

Es ist keine wirklich neue Antwort, aber - bei Verwendung von img2pdf kam die Seitengröße nicht richtig heraus. Hier ist, was ich getan habe, um die Bildgröße zu verwenden. Ich hoffe, es findet jemanden gut:

Angenommen, 1) alle Bilder haben die gleiche Größe, 2) ein Bild pro Seite platziert, 3) das Bild füllt die gesamte Seite aus

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 ))
svinec
quelle
1

Hier ist die Antwort von ilovecomputer in eine Funktion gepackt und direkt verwendbar. Es ermöglicht auch die Reduzierung der Bildgröße und funktioniert gut.

Der Code setzt einen Ordner in input_dir voraus, der Bilder enthält, die alphabetisch nach ihrem Namen sortiert sind, und gibt ein PDF mit dem Namen des Ordners und möglicherweise einer Präfixzeichenfolge für den Namen aus.

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];
Faysou
quelle
Ich habe versucht, die Dateigröße zu ändern, indem ich verschiedene resolutionWerte (wie in anderen Antworten vorgeschlagen) ohne Erfolg übergeben habe. Der qualityParameter hat es geschafft.
Tonechas
Ja, ich hatte das gleiche Problem.
Faysou
0

Einige Änderungen, um ein PDF aus dem Verzeichnis zu erstellen, in dem sich die Dateien befinden

Ich nehme den Code und habe einige geringfügige Änderungen vorgenommen, um ihn so wie er ist verwendbar zu machen.

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)
Giovanni G. PY
quelle
0

Ich hatte das gleiche Problem, also habe ich eine Python-Funktion erstellt, um mehrere Bilder in einem PDF zu vereinen. Der Code (verfügbar auf meiner Github-Seite , verwendet reportlabund basiert auf Antworten über die folgenden Links:

Hier ist ein Beispiel für das Zusammenführen von Bildern zu PDF:

Wir haben den Ordner "D: \ images" mit Bildern vom Typ png und jpg, und wir möchten daraus die Datei pdf_with_pictures.pdf erstellen und im selben Ordner speichern.

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)
Valeriy Ivanov
quelle
0

Die beste Antwort gibt es bereits !!! Ich verbessere nur die Antwort ein wenig. Hier ist der Code:

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

Zu diesem Zweck müssen Sie FPDF installieren.

pip install FPDF
Shekhar Chander
quelle
0

Gebrauchsfertige Lösung, die alle PNGs im aktuellen Ordner in ein PDF konvertiert, inspiriert von der Antwort von @ ilovecomputer:

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:])

Nichts anderes als PIL wird benötigt :)

Basj
quelle
0

Wenn sich Ihre Bilder im Querformat befinden, können Sie dies tun.

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

Hier ist page_width und page_height die Größe von 'A4'-Papier, wobei im Querformat die Breite 297 mm und die Höhe 210 mm beträgt. aber hier habe ich die höhe nach meinem bild eingestellt. ODER Sie können entweder das Seitenverhältnis beibehalten, wie ich oben kommentiert habe, um die Breite und Höhe des Bildes richtig zu skalieren.

Varat Vohra
quelle
0

Ich weiß, das ist eine alte Frage. In meinem Fall verwende ich Reportlab.

Die Blattabmessungen werden in Punkten und nicht in Pixeln ausgedrückt, wobei der Punkt 1/72 Zoll entspricht. Ein A4-Blatt besteht aus einer Breite von 595,2 Punkten und einer Höhe von 841,8 Punkten. Der Ursprung der Positionskoordinaten (0, 0) liegt in der unteren linken Ecke. Beim Erstellen einer Instanz von canvas.Canvas können Sie die Größe der Blätter mithilfe des Parameters pagesize angeben und ein Tupel übergeben, dessen erstes Element die Breite in Punkten und das zweite die Höhe darstellt. Die Methode c.showPage () teilt ReportLab mit, dass die Arbeit am aktuellen Blatt bereits abgeschlossen ist, und fährt mit dem nächsten fort. Obwohl ein zweites Blatt noch nicht bearbeitet wurde (und nicht im Dokument angezeigt wird, solange nichts gezeichnet wurde), sollten Sie dies vor dem Aufrufen von c.save () beachten. Zum Einfügen von Bildern in ein PDF-Dokument verwendet ReportLab die Kissenbibliothek. Die drawImage () -Methode verwendet als Argument den Pfad eines Bildes (unterstützt mehrere Formate wie PNG, JPEG und GIF) und die Position (x, y) in dem Bild, das Sie einfügen möchten. Das Bild kann verkleinert oder vergrößert werden, indem seine Abmessungen über die Argumente width und height angezeigt werden.

Der folgende Code enthält den Namen der PDF-Datei, eine Liste mit PNG-Dateien, Koordinaten zum Einfügen von Bildern sowie die Größe für Hochformat-Briefseiten.

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)
DEUTSCHER RODRIGUEZ
quelle
0

Was in Python 3.7 und img2pdf Version 0.4.0 für mich funktioniert hat, war, etwas zu verwenden, das dem von Syed Shamikh Shabbir angegebenen Code ähnelt, aber das aktuelle Arbeitsverzeichnis unter Verwendung des Betriebssystems zu ändern, wie Stu in seinem Kommentar zu Syeds Lösung vorgeschlagen hat

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

Es ist erwähnenswert, dass diese Lösung oben jedes JPG separat in einem einzigen PDF speichert. Wenn Sie alle Ihre JPG-Dateien in nur einer PDF-Datei zusammen haben möchten, können Sie Folgendes tun:

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))
BrunoSE
quelle