In python code, how to efficiently save a certain page in a pdf as a jpeg file? (Use case: I've a python flask web server where pdf-s will be uploaded and jpeg-s corresponding to each page is stores.)
This solution is close, but the problem is that it does not convert the entire page to jpeg.
117 Answers
The pdf2image library can be used.
You can install it simply using,
pip install pdf2image Once installed you can use following code to get images.
from pdf2image import convert_from_path pages = convert_from_path('pdf_file', 500) Saving pages in jpeg format
for page in pages: page.save('out.jpg', 'JPEG') Edit: the Github repo pdf2image also mentions that it uses pdftoppm and that it requires other installations:
pdftoppm is the piece of software that does the actual magic. It is distributed as part of a greater package called poppler. Windows users will have to install poppler for Windows. Mac users will have to install poppler for Mac. Linux users will have pdftoppm pre-installed with the distro (Tested on Ubuntu and Archlinux) if it's not, run
sudo apt install poppler-utils.
You can install the latest version under Windows using anaconda by doing:
conda install -c conda-forge poppler note: Windows versions upto 0.67 are available at but note that 0.68 was released in Aug 2018 so you'll not be getting the latest features or bug fixes.
16I found this simple solution, PyMuPDF, output to png file. Note the library is imported as "fitz", a historical name for the rendering engine it uses.
import fitz pdffile = "infile.pdf" doc = fitz.open(pdffile) page = doc.loadPage(0) # number of page pix = page.get_pixmap() output = "outfile.png" pix.save(output) 9The Python library pdf2image (used in the other answer) in fact doesn't do much more than just launching pdttoppm with subprocess.Popen, so here is a short version doing it directly:
PDFTOPPMPATH = r"D:\Documents\software\____PORTABLE\poppler-0.51\bin\pdftoppm.exe" PDFFILE = "SKM_28718052212190.pdf" import subprocess subprocess.Popen('"%s" -png "%s" out' % (PDFTOPPMPATH, PDFFILE)) Here is the Windows installation link for pdftoppm (contained in a package named poppler): .
There is no need to install Poppler on your OS. This will work:
pip install Wand
from wand.image import Image f = "somefile.pdf" with(Image(filename=f, resolution=120)) as source: for i, image in enumerate(source.sequence): newfilename = f[:-4] + str(i + 1) + '.jpeg' Image(image).save(filename=newfilename) 4@gaurwraith, install poppler for Windows and use pdftoppm.exe as follows:
Download zip file with Poppler's latest binaries/dlls from and unzip to a new folder in your program files folder. For example: "C:\Program Files (x86)\Poppler".
Add "C:\Program Files (x86)\Poppler\poppler-0.68.0\bin" to your SYSTEM PATH environment variable.
From cmd line install pdf2image module -> "pip install pdf2image".
- Or alternatively, directly execute pdftoppm.exe from your code using Python's subprocess module as explained by user Basj.
@vishvAs vAsuki, this code should generate the jpgs you want through the subprocess module for all pages of one or more pdfs in a given folder:
import os, subprocess pdf_dir = r"C:\yourPDFfolder" os.chdir(pdf_dir) pdftoppm_path = r"C:\Program Files (x86)\Poppler\poppler-0.68.0\bin\pdftoppm.exe" for pdf_file in os.listdir(pdf_dir): if pdf_file.endswith(".pdf"): subprocess.Popen('"%s" -jpeg %s out' % (pdftoppm_path, pdf_file)) Or using the pdf2image module:
import os from pdf2image import convert_from_path pdf_dir = r"C:\yourPDFfolder" os.chdir(pdf_dir) for pdf_file in os.listdir(pdf_dir): if pdf_file.endswith(".pdf"): pages = convert_from_path(pdf_file, 300) pdf_file = pdf_file[:-4] for page in pages: page.save("%s-page%d.jpg" % (pdf_file,pages.index(page)), "JPEG") 2Using pypdfium2:
python3 -m pip install pypdfium2 # Load a document filepath = "tests/resources/multipage.pdf" pdf = pdfium.PdfDocument(filepath) # render a single page (in this case: the first one) page = pdf.get_page(0) pil_image = page.render_topil() pil_image.save("output.jpg") page.close() # render multiple pages concurrently (in this case: all) page_indices = [i for i in range(len(pdf))] renderer = pdf.render_topil( page_indices = page_indices, ) for image, index in zip(renderer, page_indices): image.save("output_%02d.jpg" % index) image.close() pdf.close() Advantages:
- PDFium is liberal-licensed (BSD 3-Clause or Apache 2.0, at your choice)
- It is fast, outperforming Poppler. In terms of speed, pypdfium2 can almost reach
PyMuPDF - Returns
PIL.Image.Image, bytes, or a ctypes array, depending on your needs - Is capable of processing encrypted (password-protected) PDFs
- No runtime dependencies except
PIL, which is optional - Supports Python >= 3.5
- Setup infrastructure complies with PEP 517/518, while legacy setup still works as well
Wheels are currently available for
Windowsamd64, win32, arm64macOSx86_64, arm64Linux (glibc)x86_64, i686, aarch64, armv7lLinux (musl)x86_64, i686
There is a script to build from source, too.
(Disclaimer: I'm the author)
GhostScript performs much faster than Poppler for a Linux based system.
Following is the code for pdf to image conversion.
def get_image_page(pdf_file, out_file, page_num): page = str(page_num + 1) command = ["gs", "-q", "-dNOPAUSE", "-dBATCH", "-sDEVICE=png16m", "-r" + str(RESOLUTION), "-dPDFFitPage", "-sOutputFile=" + out_file, "-dFirstPage=" + page, "-dLastPage=" + page, pdf_file] f_null = open(os.devnull, 'w') subprocess.call(command, stdout=f_null, stderr=subprocess.STDOUT) GhostScript can be installed on macOS using brew install ghostscript
Installation information for other platforms can be found here. If it is not already installed on your system.
2Their is a utility called pdftojpg which can be used to convert the pdf to img
from pdf2jpg import pdf2jpg inputpath = r"D:\inputdir\pdf1.pdf" outputpath = r"D:\outputdir" # To convert single page result = pdf2jpg.convert_pdf2jpg(inputpath, outputpath, pages="1") print(result) # To convert multiple pages result = pdf2jpg.convert_pdf2jpg(inputpath, outputpath, pages="1,0,3") print(result) # to convert all pages result = pdf2jpg.convert_pdf2jpg(inputpath, outputpath, pages="ALL") print(result) 2One problem,everyone will face that is to Install Poppler.My way is a tricky way,but will work efficiently.1st download Poppler here.Then Extract it add In the code section just add poppler_path=r'C:\Program Files\poppler-0.68.0\bin'(for eg.) like below
from pdf2image import convert_from_path images = convert_from_path("mypdf.pdf", 500,poppler_path=r'C:\Program Files\poppler-0.68.0\bin') for i, image in enumerate(images): fname = 'image'+str(i)+'.png' image.save(fname, "PNG") 1Here is a function that does the conversion of a PDF file with one or multiple pages to a single merged JPEG image.
import os import tempfile from pdf2image import convert_from_path from PIL import Image def convert_pdf_to_image(file_path, output_path): # save temp image files in temp dir, delete them after we are finished with tempfile.TemporaryDirectory() as temp_dir: # convert pdf to multiple image images = convert_from_path(file_path, output_folder=temp_dir) # save images to temporary directory temp_images = [] for i in range(len(images)): image_path = f'{temp_dir}/{i}.jpg' images[i].save(image_path, 'JPEG') temp_images.append(image_path) # read images into pillow.Image imgs = list(map(Image.open, temp_images)) # find minimum width of images min_img_width = min(i.width for i in imgs) # find total height of all images total_height = 0 for i, img in enumerate(imgs): total_height += imgs[i].height # create new image object with width and total height merged_image = Image.new(imgs[0].mode, (min_img_width, total_height)) # paste images together one by one y = 0 for img in imgs: merged_image.paste(img, (0, y)) y += img.height # save merged image merged_image.save(output_path) return output_path Example usage: -
convert_pdf_to_image("path_to_Pdf/1.pdf", "output_path/output.jpeg")
I wrote this script to easily convert a folder directory that contains PDFs (single page) to PNGs really nicely.
import os from pathlib import PurePath import glob # from PIL import Image from pdf2image import convert_from_path import pdb # In[file list] wd = os.getcwd() # filter images fileListpdf = glob.glob(f'{wd}//*.pdf') # In[Convert pdf to images] for i in fileListpdf: images = convert_from_path(i, dpi=300) path_split = PurePath(i).parts fileName, ext = os.path.splitext(path_split[-1]) images[0].save(f'{fileName}.png', 'PNG') Hopefully, this helps if you need to convert PDFs to PNGs!
I use a (maybe) much simpler option of pdf2image:
cd $dir for f in *.pdf do if [ -f "${f}" ]; then n=$(echo "$f" | cut -f1 -d'.') pdftoppm -scale-to 1440 -png $f $conv/$n rm $f mv $conv/*.png $dir fi done This is a small part of a bash script in a loop for the use of a narrow casting device. Checks every 5 seconds on added pdf files (all) and processes them. This is for a demo device, at the end converting will be done at a remote server. Converting to .PNG now, but .JPG is possible too.
This converting, together with transitions on A4 format, displaying a video, two smooth scrolling texts and a logo (with transition in three versions) sets the Pi3 to allmost 4x 100% cpu-load ;-)
1from pdf2image import convert_from_path import glob pdf_dir = glob.glob(r'G:\personal\pdf\*') #your pdf folder path img_dir = "G:\\personal\\img\\" #your dest img path for pdf_ in pdf_dir: pages = convert_from_path(pdf_, 500) for page in pages: page.save(img_dir+pdf_.split("\\")[-1][:-3]+"jpg", 'JPEG') 2Here is a solution which requires no additional libraries and is very fast. This was found from: I have added the code in a function to make it more convenient.
def convert(filepath): with open(filepath, "rb") as file: pdf = file.read() startmark = b"\xff\xd8" startfix = 0 endmark = b"\xff\xd9" endfix = 2 i = 0 njpg = 0 while True: istream = pdf.find(b"stream", i) if istream < 0: break istart = pdf.find(startmark, istream, istream + 20) if istart < 0: i = istream + 20 continue iend = pdf.find(b"endstream", istart) if iend < 0: raise Exception("Didn't find end of stream!") iend = pdf.find(endmark, iend - 20) if iend < 0: raise Exception("Didn't find end of JPG!") istart += startfix iend += endfix jpg = pdf[istart:iend] newfile = "{}jpg".format(filepath[:-3]) with open(newfile, "wb") as jpgfile: jpgfile.write(jpg) njpg += 1 i = iend return newfile Call convert with the pdf path as the argument and the function will create a .jpg file in the same directory
1For a pdf file with multiple pages, the following is the best & simplest (I used pdf2image-1.14.0):
from pdf2image import convert_from_path from pdf2image.exceptions import ( PDFInfoNotInstalledError, PDFPageCountError, PDFSyntaxError ) images = convert_from_path(r"path/to/input/pdf/file", output_folder=r"path/to/output/folder", fmt="jpg",) #dpi=200, grayscale=True, size=(300,400), first_page=0, last_page=3) images.clear() Note:
- "images" is a list of PIL images.
- The saved images in the output folder will have system generated names; one can later change them, if required.
This easy script can convert a folder directory that contains PDFs (single/multiple pages) to jpeg.
from PIL import Image import pytesseract import sys from pdf2image import convert_from_path import os from os import listdir from os import system from os.path import isfile, join, basename, dirname import shutil def move_processed_file(file, doc_path, download_processed): try: shutil.move(doc_path + '/' + file, download_processed + '/' + file) pass except Exception as e: print(e.errno) raise else: pass finally: pass pass def run_conversion(): root_dir = os.path.abspath(os.curdir) doc_path = root_dir + r"\data\download" pdf_processed = root_dir + r"\data\download\pdf_processed" results_folder = doc_path files = [f for f in listdir(doc_path) if isfile(join(doc_path, f))] pdf_files = [f for f in listdir(doc_path) if isfile(join(doc_path, f)) and f.lower().endswith('.pdf')] # check OS type if os.name == 'nt': # if is windows or a graphical OS, change this poppler path with your own path poppler_path = r"C:\poppler-0.68.0\bin" else: poppler_path = root_dir + r"\usr\bin" for file in pdf_files: ''' # Converting PDF to images ''' # Store all the pages of the PDF in a variable pages = convert_from_path(doc_path + '/' + file, 500, poppler_path=poppler_path) # Counter to store images of each page of PDF to image image_counter = 1 filename, file_extension = os.path.splitext(file) # Iterate through all the pages stored above for page in pages: # Declaring filename for each page of PDF as JPG # PDF page n -> page_n.jpg filename = filename + '_' + str(image_counter) + ".jpg" # Save the image of the page in system page.save(results_folder + '/' + filename, 'JPEG') # Increment the counter to update filename image_counter += 1 move_processed_file(file, doc_path, pdf_processed) from pdf2image import convert_from_path PDF_file = 'Statement.pdf' pages = convert_from_path(PDF_file, 500,userpw='XXX') image_counter = 1 for page in pages: filename = "foldername/page_" + str(image_counter) + ".jpg" page.save(filename, 'JPEG') image_counter = image_counter + 1 1