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