|
#!/usr/bin/env python |
|
# -*- 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"] |
|
__doc__ = """ |
|
This tool aims to generate preview images of an input PDF (e.g. a book). |
|
""" |
|
|
|
|
|
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.ANTIALIAS) |
|
|
|
|
|
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)) |