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