'Extract a page from a pdf as a jpeg
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.
Solution 1:[1]
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 http://blog.alivate.com.au/poppler-windows/ but note that 0.68 was released in Aug 2018 so you'll not be getting the latest features or bug fixes.
Solution 2:[2]
I 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)
Solution 3:[3]
The 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): http://blog.alivate.com.au/poppler-windows/.
Solution 4:[4]
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)
Solution 5:[5]
@gaurwraith, install poppler for Windows and use pdftoppm.exe as follows:
Download zip file with Poppler's latest binaries/dlls from http://blog.alivate.com.au/poppler-windows/ 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")
Solution 6:[6]
Using pypdfium2
:
python3 -m pip install pypdfium2
import pypdfium2 as pdfium
pdffile = 'path/to/your_doc.pdf'
# render multiple pages concurrently (in this case: all)
for image, suffix in pdfium.render_pdf_topil(pdffile):
image.save('output_%s.jpg' % suffix)
# render a single page (in this case: the first one)
with pdfium.PdfContext(pdffile) as pdf:
image = pdfium.render_page_topil(pdf, 0)
image.save('output.jpg')
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
Windows
amd64, win32, arm64macOS
x86_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)
Solution 7:[7]
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.
Solution 8:[8]
Their is a utility called pdftojpg which can be used to convert the pdf to img
You can found the code here https://github.com/pankajr141/pdf2jpg
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)
Solution 9:[9]
One 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")
Solution 10:[10]
Here 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")
Solution 11:[11]
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!
Solution 12:[12]
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 ;-)
Solution 13:[13]
from 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')
Solution 14:[14]
Here is a solution which requires no additional libraries and is very fast. This was found from: https://nedbatchelder.com/blog/200712/extracting_jpgs_from_pdfs.html# 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
Solution 15:[15]
For 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.
Solution 16:[16]
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)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow