128

Is there any practical way to create a PDF from a list of images files, using Python?

In Perl I know that module. With it I can create a PDF in just 3 lines:

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

I need to do something very similar to this, but in Python. I know the pyPdf module, but I would like something simple.

ggorlen
  • 44,755
  • 7
  • 76
  • 106
macabeus
  • 4,156
  • 5
  • 37
  • 66

22 Answers22

130

The best method to convert multiple images to PDF I have tried so far is to use PIL purely. It's quite simple yet powerful:

from PIL import Image  # install by > python3 -m pip install --upgrade Pillow  # ref. https://pillow.readthedocs.io/en/latest/installation.html#basic-installation

images = [
    Image.open("/Users/apple/Desktop/" + f)
    for f in ["bbd.jpg", "bbd1.jpg", "bbd2.jpg"]
]

pdf_path = "/Users/apple/Desktop/bbd1.pdf"
    
images[0].save(
    pdf_path, "PDF" ,resolution=100.0, save_all=True, append_images=images[1:]
)

Just set save_all to True and append_images to the list of images which you want to add.

You might encounter the AttributeError: 'JpegImageFile' object has no attribute 'encoderinfo'. The solution is here Error while saving multiple JPEGs as a multi-page PDF

Note:Install the newest PIL to make sure save_all argument is available for PDF.

p.s.

In case you get this error

cannot save mode RGBA

apply this fix

png = Image.open('/path/to/your/file.png')
png.load()
background = Image.new("RGB", png.size, (255, 255, 255))
background.paste(png, mask=png.split()[3]) # 3 is the alpha channel
Nam G VU
  • 33,193
  • 69
  • 233
  • 372
ilovecomputer
  • 4,238
  • 1
  • 20
  • 33
  • 5
    Best method, directly with PIL! – Basj May 22 '20 at 11:12
  • this approach work for me. – Nitendra Oct 25 '21 at 08:25
  • Best answer. This is also around 2x faster than ilya-vinnichenko's answer i.e. looping all the images and adding to the pdf one by one. – Prince Mathur Jan 20 '22 at 15:27
  • 3
    FYI: the code could be also improved by adding a generator for `append_images`, something like `Image.open(image_paths[0]).save(..., append_images=(Image.open(f) for f in image_paths[1:]))` (with `image_paths` being a list of paths of the images for the pages). This will avoid storing in memory a lot of `Image` objects. – Jean-Francois T. Feb 22 '22 at 06:11
  • @ilovecomputer Thanks a lot for the code. Is there a way to control the width and height of the output pdf? – YasserKhalil Mar 02 '22 at 18:42
  • This easy and simple approach worked for me – Yaser Sakkaf Jan 20 '23 at 10:33
112

Install FPDF for Python:

pip install fpdf

Now you can use the same logic:

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

You can find more info at the tutorial page or the official documentation.

Adam Matan
  • 128,757
  • 147
  • 397
  • 562
Ilya Vinnichenko
  • 1,215
  • 1
  • 11
  • 3
  • 3
    Thank you, but I could not success. The images I'm working on are JPG; the FDPF not have native support for JPG. For this, need the PIL. As the PIL has no more support for Python 3, I installed PILLOW. However, the FDPF apparently does not recognize: "PIL not installed". For testing purposes, I tested with PNG images, however, results in the following error: "Not a PNG file: 0.png" – macabeus Dec 06 '14 at 17:17
  • @KeplerBR Well above in my answer I have used `pgmagick' which supports `jpg, png, JPEG 2000` and many other formats and results great in image to pdf conversion too. – Tanveer Alam Dec 06 '14 at 18:12
  • What wonderful! After a few months, I decided to return to the project that gave me this problem, and tried again using FPDF, now with the latest version, and now worked perfectly! Thank you! I edited the original post with the complete code, for those who come here through Google. – macabeus Feb 21 '15 at 04:35
  • 27
    For A4 size paged pdfs, the value for w and h is 210 and 297, respectively. – GiriB Jul 30 '16 at 17:59
  • 5
    The issue I encountered with this approach is that every other page is blank for some reason. – nimdil Nov 10 '16 at 16:58
  • 9
    Can you tell what are the values for x,y,w and h ? – Prajwal Jun 19 '18 at 15:16
  • yea, I also encountered the blank pages, any idea why that is? – Fabian Bosler Jul 26 '18 at 13:47
  • For the blank pages, this here worked for me: https://stackoverflow.com/a/47149023/8616306 – Epiousios Jun 25 '19 at 10:49
  • 10
    for standard (a4) pages, what should the values be for x,y,w,h? edit: looks like 0,0,210,297 works – j413254 Sep 29 '20 at 05:40
  • hi I tried this, but i'm getting an error ```RuntimeError: FPDF error: Unsupported image type: webp``` is there any way to solve it or any alternative lib which accepts .webp images. – sandeepnegi Dec 26 '22 at 11:20
63

If you use Python 3, you can use the python module img2pdf

install it using pip3 install img2pdf and then you can use it in a script using import img2pdf

sample code

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

or (If you get any error with previous approach due to some path issue)

# convert all files matching a glob
import glob
with open("name.pdf","wb") as f:
    f.write(img2pdf.convert(glob.glob("/path/to/*.jpg")))
teddcp
  • 1,514
  • 2
  • 11
  • 25
Syed Shamikh Shabbir
  • 1,252
  • 1
  • 14
  • 18
  • 1
    I could not get it to work specifying the directory with a string. I had to first change directory with `os.chdir('path')` and then `[i for i in os.listdir(os.getcwd()) if i.endswith(".jpg")]` – Stu Sep 27 '18 at 14:00
  • 7
    TypeError: Neither implements read() nor is str or bytes Gives this error – Palak Bansal Aug 13 '19 at 08:42
  • 3
    This used to work for me, but not I get a type error: a bytes-like object is required, not str – FreyGeospatial Mar 24 '22 at 17:40
8

If your images are plots you created mith matplotlib, you can use 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()
Qaswed
  • 3,649
  • 7
  • 27
  • 47
5

pgmagick is a GraphicsMagick(Magick++) binding for Python.

It's is a Python wrapper for for ImageMagick (or 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:

enter image description here

PDF looks like this:

enter image description here

pgmagick iinstallation instruction for windows:

1) Download precompiled binary packages from the Unofficial Windows Binaries for Python Extension Packages (as mentioned in the pgmagick web page) and install it.

Note: Try to download correct version corresponding to your python version installed in your machine and whether its 32bit installation or 64bit.

You can check whether you have 32bit or 64bit python by just typing python at your terminal and press Enter..

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.

So it has python version 2.7 and its of 32 bit (Intel)] on win32 so you have to downlad and install pgmagick‑0.5.8.win32‑py2.7.exe.

These are the following available Python Extension Packages for 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) Then you can follow installation instruction from here.

pip install pgmagick

An then try to import it.

>>> from pgmagick import gminfo
>>> gminfo.version
'1.3.x'
>>> gminfo.library
'GraphicsMagick'
>>>
Tanveer Alam
  • 5,185
  • 4
  • 22
  • 43
  • I saw your answer, but I can not make the installation of ImageMagick. When I try to install the module, I always get the error message "Magick ++ not found". I tried installing by the binaries. Seem to have been successfully installed, but does not seem taking effect. I really need to install over the source? Or did I something wrong? – macabeus Dec 06 '14 at 20:02
  • @KeplerBR Which operating system you are using? Yeah I know Magic++ is the dependency required to install pgmagick but its worth it because it amazing in many cases. – Tanveer Alam Dec 06 '14 at 21:06
  • 1
    @KeplerBR See above I have added installation instruction of pgmagick for windows. – Tanveer Alam Dec 07 '14 at 02:24
  • I saw the lfd page, however, I'm using python 3.4 and it supports up to 3.2. I can not compile successfully source. There would be otherwise, or I'll have to compile? – macabeus Dec 07 '14 at 02:44
  • You should try to complite it or other wise swtiching back to Python 3.2 is also one option. – Tanveer Alam Dec 07 '14 at 02:54
4
**** 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")
Harsh Wardhan
  • 2,110
  • 10
  • 36
  • 51
user7384403
  • 189
  • 1
  • 3
4

first pip install pillow in terminal. Images can be in jpg or png format. if you have 2 or more images and want to make in 1 pdf file.

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
  • 79
  • 1
  • 3
3

How about this??

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")
Fabian
  • 1,130
  • 9
  • 25
3

Some changes to make a pdf from the dir where the files are

I take the code and made some slight change to make it useable as it is.

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)
PythonProgrammi
  • 22,305
  • 3
  • 41
  • 34
2

I know the question has been answered but one more way to solve this is using the pillow library. To convert a whole directory of images:

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)

For using it on an single image:

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
  • 139
  • 3
  • 6
2

It's not a truly new answer, but - when using img2pdf the page size didn't come out right. So here's what I did to use the image size, I hope it finds someone well:

assuming 1) all images are the same size, 2) placing one image per page, 3) image fills the whole page

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
  • 679
  • 8
  • 9
2

Here is ilovecomputer's answer packed into a function and directly usable. It also allows to reduce image sizes and works well.

The code assumes a folder inside input_dir that contains images ordered alphabetically by their name and outputs a pdf with the name of the folder and potentially a prefix string for the name.

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
  • 1,142
  • 11
  • 25
2

What worked for me in python 3.7 and img2pdf version 0.4.0 was to use something similar to the code given by Syed Shamikh Shabbir but changing the current working directory using OS as Stu suggested in his comment to Syed's solution

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

It is worth mentioning this solution above saves each .jpg separately in one single pdf. If you want all your .jpg files together in only one .pdf you could do:

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
  • 94
  • 4
2

In my case there was need to convert more then 100 images in different formats (with and with out alpha channel and with different extensions).

I tried all the recepts from answers to this question.

Pil => cannot combine with and without alpha channel (neet to convert images)

fpdf => stack on lots of images

print from html in gotenberg => extremely long processing

And my last attempt was reportlab. And it works nice and fast. (But produce corrupted pdf sometimes on big input). Here is my code

from PyPDF2 import PdfMerger
from reportlab.lib.pagesizes import letter
from reportlab.lib.units import inch
from reportlab.platypus import Image, PageBreak, Paragraph, SimpleDocTemplate

async def save_report_lab_story_to_pdf(file_name, story):
    doc = SimpleDocTemplate(
        file_name,
        pagesize=letter,
        rightMargin=32,
        leftMargin=32,
        topMargin=18,
        bottomMargin=18,
    )
    doc.build(story)


async def reportlab_pdf_builder(data, images):
    story = []
    width = 7.5 * inch
    height = 9 * inch

    chunk_size = 5 * 70
    pdf_chunks = []

    files_to_clean_up = []
    for trip in data['trips']:
        for invoice in trip['invoices']:
            for page in invoice['pages']:
                if trip['trip_label']:
                    story.append(Paragraph(
                        f"TRIP: {trip['trip_label']} {trip['trip_begin']} - {trip['trip_end']}"
                    ))
                else:
                    story.append(Paragraph("No trip"))

                story.append(Paragraph(
                    f"""Document number: {invoice['invoice_number']}
                        Document date: {invoice['document_date']}
                        Amount: {invoice['invoice_trip_value']} {invoice['currency_code']}
                    """
                ))
                story.append(Paragraph(" "))
                img_name = page['filename']
                img_bytes = images[page['path']]
                tmp_img_filename = f'/tmp/{uuid.uuid4()}.{img_name}'
                with open(tmp_img_filename, "wb") as tmp_img:
                    tmp_img.write(img_bytes)
                im = Image(tmp_img_filename, width, height)
                story.append(im)
                story.append(PageBreak())
                files_to_clean_up.append(tmp_img_filename)
                # 5 objects per page in story

                if len(story) >= chunk_size:
                    file_name = f"/tmp/{uuid.uuid4()}_{data['tail_number']}.pdf"
                    await save_report_lab_story_to_pdf(file_name, story)
                    story = []
                    pdf_chunks.append(file_name)

    merger = PdfMerger()
    for pdf in pdf_chunks:
        merger.append(pdf)

    res_file_name = f"/tmp/{uuid.uuid4()}_{data['tail_number']}.pdf"
    merger.write(res_file_name)
    merger.close()
Ryabchenko Alexander
  • 10,057
  • 7
  • 56
  • 88
1

I had the same problem, so I created a python function to unite multiple pictures in one pdf. The code (available from my github page, uses reportlab, and is based on answers from the following links:

Here is example of how to unite images into pdf:

We have folder "D:\pictures" with pictures of types png and jpg, and we want to create file pdf_with_pictures.pdf out of them and save it in the same folder.

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)
Andy
  • 61,948
  • 13
  • 68
  • 95
1

Ready-to-use solution that converts all PNG in the current folder to a PDF, inspired by @ilovecomputer's answer:

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

Nothing else than PIL is needed :)

Basj
  • 41,386
  • 99
  • 383
  • 673
1

If your images are in landscape mode, you can do like this.

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

Here page_width and page_height is the size of 'A4' paper where in landscape its width will 297mm and height will be 210mm; but here I have adjusted the height as per my image. OR you can use either maintaining the aspect ratio as I have commented above for proper scaling of both width and height of the image.

VARAT BOHARA
  • 396
  • 2
  • 6
1

I know this is an old question. In my case I use Reportlab.

Sheet dimensions are expressed in points, not pixels, with a point equal to 1/72 inch. An A4 sheet is made up of 595.2 points width and 841.8 points height. The origin of the position coordinates (0, 0) is in the lower left corner. When creating an instance of canvas.Canvas, you can specify the size of the sheets using the pagesize parameter, passing a tuple whose first element represents the width in points and the second, the height. The c.showPage () method tells ReportLab that it has already finished working on the current sheet and moves on to the next one. Although a second sheet has not yet been worked on (and will not appear in the document as long as nothing has been drawn) it is good practice to remember to do so before invoking c.save (). To insert images into a PDF document, ReportLab uses the Pillow library. The drawImage () method takes as its argument the path of an image (supports multiple formats such as PNG, JPEG and GIF) and the position (x, y) in the that you want to insert. The image can be reduced or enlarged indicating its dimensions via the width and height arguments.

The following code provides pdf file name, list with png files, coordinates to insert images as well as size to fit in portrait letter pages.

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)
GERMAN RODRIGUEZ
  • 397
  • 1
  • 4
  • 9
1

You can use pdfme. It's the most powerful library in python to create PDF documents.

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

Check the docs here

Felipe Sierra
  • 143
  • 2
  • 12
0

The best answer already exists !!! I am just improving the answer a little bit. Here's the 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")

You'll need to install FPDF for this purpose.

pip install FPDF
shekhar chander
  • 600
  • 8
  • 14
0

Adding to @ilovecomputer's answer, if you want to keep pdf in memory rather than disk, then you can do this:

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()
Prince Mathur
  • 309
  • 3
  • 4
0

This answer seemed legit but I couldn't get it to work due to the error "a bytes-like object is required, not str". After reading the img2pdf documentation, this is what worked for me:

import img2pdf
import os

dirname = "/path/to/images"
imgs = []
for fname in os.listdir(dirname):
    if not fname.endswith(".jpg") and not fname.endswith(".png"):
        continue
    path = os.path.join(dirname, fname)
    if os.path.isdir(path):
        continue
    imgs.append(path)
with open("name.pdf","wb") as f:
    f.write(img2pdf.convert(imgs))
Validus Oculus
  • 2,756
  • 1
  • 25
  • 34
Hagbard
  • 3,430
  • 5
  • 28
  • 64