Skip to content

Instantly share code, notes, and snippets.

@dhondta
Last active December 3, 2023 18:57
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dhondta/f57dfde304905644ca5c43e48c249125 to your computer and use it in GitHub Desktop.
Save dhondta/f57dfde304905644ca5c43e48c249125 to your computer and use it in GitHub Desktop.
Tinyscript tool for generating preview image(s) of a PDF

PDF preview generator

This Tinyscript-based tool aims to generate preview images of an input PDF (e.g. a book).

This can be installed using:

$ pip install pdf2image tinyscript
$ tsm install pdf-preview-generator
#!/usr/bin/python3
# -*- coding: UTF-8 -*-
from functools import reduce
from pdf2image import convert_from_path
from PIL import Image
from tinyscript import *
__author__ = "Alexandre D'Hondt"
__version__ = "1.3"
__copyright__ = "A. D'Hondt"
__license__ = "agpl-3.0"
__examples__ = ["preview doc.pdf", "preview doc.pdf -f 4x2", "pages doc.pdf", "pages doc.pdf -p 1,3"]
preview_format = lambda f: list(map(int, f.split("x")))
def generate_preview(pdf=None, output_dir=".", preview_format=(4, 1), pages=None, npages=None, password=None, dpi=200,
action="preview", width=None, **kwargs):
if pdf is None:
logger.error("No input PDF")
return
page_imgs = convert_from_path(pdf, dpi, userpw=password)
l = len(page_imgs)
if l == 0:
logger.error("Could not convert")
return
npages = npages or len(pages or []) or reduce(lambda x, y: x * y, preview_format)
if pages is None:
pages = [0]
n = min(npages, l) - 1
for i in range(n):
b1 = pages[-1] + 1
b2 = min(max(b1, (i + 1) * l // n - 1), l - 1)
pages.append(random.randint(b1, b2))
# preview per page
if action == "pages":
for i in pages:
fn = os.path.join(output_dir, "page-{}.png".format(i))
resize_width(page_imgs[i], width or 480).save(fn)
# preview with all the selected pages
elif action == "preview":
if len(preview_format) == 1:
preview_format.append(1)
if preview_format[1] == 1:
preview_format[0] = min(preview_format[0], npages)
x, y = preview_format
w, h = page_imgs[0].size
img = Image.new('RGBA', (x * w, y * h), (255, 0, 0, 0))
for n, i in enumerate(pages):
img.paste(page_imgs[i], ((n % x) * w, (n // x) * h))
fn = os.path.join(output_dir, "preview.png")
resize_width(img, width or min(1600, x * 480)).save(fn)
else:
raise ValueError("Invalid action")
def resize_width(img, new_width=800):
w, h = img.size
if w < new_width:
return img
return img.resize((new_width, int(float(new_width) / w * h)), Image.LANCZOS)
if __name__ == '__main__':
subparsers = parser.add_subparsers(dest="action")
preview = subparsers.add_parser("preview", help="make single preview image")
preview.add_argument("-f", dest="preview_format", default="4x1", type=preview_format, help="pages preview format")
pages = subparsers.add_parser("pages", help="make page screenshots")
for i, p in enumerate([preview, pages]):
p.add_argument("--password", help="PDF password")
g = p.add_mutually_exclusive_group()
p.add_argument("pdf", type=ts.file_exists, help="PDF filename")
p.add_argument("-d", dest="dpi", type=ts.pos_int, default=200, help="image quality in DPI")
g.add_argument("-n", dest="npages", type=ts.pos_int, help="number of randomly chosen pages")
p.add_argument("-o", dest="output_dir", default=".", type=ts.folder_exists,
help="output folder for the generated image(s)")
g.add_argument("-p", dest="pages", type=ts.pos_ints, help="list of pages to be inserted in the preview")
if i == 0:
p.add_argument("-w", dest="width", type=ts.pos_int, help="width of the target preview image in pixels",
note="if not set, will be NX_PAGES * 480px with max 1600px")
else:
p.add_argument("-w", dest="width", default=480, type=ts.pos_int, help="width of the pages in pixels")
initialize()
generate_preview(**vars(args))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment