Python调用ImageMagick生成PDF文件缩略图

使用Python调用ImageMagick生成PDF文件缩略图

Imagemagick使用Ghostscript作为其依赖项之一,以便能够处理和转换PDF相关的图像。

准备

安装完毕后,需要自行配置环境路径

脚本

使用示例:

python .\get_thumbnail.py --filepath .\paper.pdf --page [4-8,12-17,20,24,27-] --output-dir test-dir

输出:

result

支持灵活传入页面参数
[ 4 − 8 , 12 − 17 , 20 , 24 , 27 − ] [4-8,12-17,20,24,27-] [48,1217,20,24,27]

  • 4-8、12-17:第4页到第8页、第12页到第17页
  • 20、24:第20页、第24页
  • 27-:从第27页到最后一页
import subprocess
import argparse
from pathlib import Path
from math import sqrt

# 解析参数
parser = argparse.ArgumentParser()
parser.add_argument("--filepath", type=str, help="pdf文件路径")
parser.add_argument(
    "--page",
    type=str,
    default="all",
    help="指定要生成缩略图的pdf文件页面 e.[1-3,8,10,27-] 默认为全部页面",
)
parser.add_argument("--shape", type=str, default="cube", help="指定缩略图的形状 e.[8x3] 默认为正方形")
parser.add_argument("--output-dir", type=str, default="./images", help="指定输出文件夹")
args = parser.parse_args()


# 写一个函数,调用外部程序获取pdf文件总页数
def get_file_page_num(filepath: str):
    result = subprocess.run(
        ["magick", "identify", "-format", "%n", filepath], stdout=subprocess.PIPE
    )
    # 获取命令行输出
    output = result.stdout.decode("utf-8")
    for i in range(1, 4):
        if len(output) == i * int(output[:i]):
            return int(output[:i])


# 预处理参数
# 获取目标页面总数目以及详细页码
def get_dst_page(filepath: str, page_str: str):
    total_num = 0
    detail_page = []
    if page_str == "all":
        total_num = get_file_page_num(filepath)
        detail_page.append((1, total_num))
    else:
        for item in page_str.replace(" ", "")[1:-1].split(","):
            if "-" not in item:
                total_num += 1
                detail_page.append(int(item))
            if "-" in item and not item.endswith("-"):
                start, end = list(map(lambda x: int(x), item.split("-")))
                total_num += end - start + 1
                detail_page.append((start, end))
            if "-" in item and item.endswith("-"):
                start = int(item[:-1])
                end = get_file_page_num(filepath)
                total_num += end - start
                detail_page.append((start, end - 1))
    return total_num, detail_page


def get_per_page_idx(detail_page_scope: list):
    pages = []
    for item in detail_page_scope:
        if isinstance(item, tuple):
            for i in range(item[0], item[1] + 1):
                pages.append(i)
        else:
            pages.append(item)
    return pages


# 自动推断比较合适的形状
def infer_shape(num):
    H = int(sqrt(num / sqrt(2)))
    W = int(num / H + 1)
    if H * W < num:
        H += 1
    return W, H


def get_shape(num):
    if args.shape == "cube":
        shape = infer_shape(num)
        return f"{shape[0]}x{shape[1]}"
    else:
        return args.shape.replace(" ", "")


if __name__ == "__main__":
    if not Path(args.output_dir).exists():
        Path(args.output_dir).mkdir()
    total_num, detail_page = get_dst_page(args.filepath, args.page)
    # 调用外部程序将每个指定的页面转换为缩略图
    # 必须指定"-alpha remove",否则生成的图片背景永远是黑色
    for item in detail_page:
        if isinstance(item, tuple):
            subprocess.run(
                [
                    "magick",
                    "convert",
                    "-thumbnail",
                    "x800",
                    "-alpha",
                    "remove",
                    f"{args.filepath}[{item[0]}-{item[1]}]",
                    str(Path(args.output_dir) / "output.png"),
                ],
                shell=True,
            )
        else:
            subprocess.run(
                [
                    "magick",
                    "convert",
                    "-thumbnail",
                    "x800",
                    "-alpha",
                    "remove",
                    f"{args.filepath}[{item}]",
                    str(Path(args.output_dir) / f"output-{item}.png"),
                ],
                shell=True,
            )

    print("参与生成缩略图的页面为:", get_per_page_idx(detail_page))
    image_list = list(
        map(
            lambda x: str(Path(args.output_dir) / f"output-{x}.png"),
            get_per_page_idx(detail_page),
        )
    )
    # 调用外部程序合并缩略图
    subprocess.run(
        [
            "magick",
            "montage",
            *image_list,
            "-geometry",
            "+0+0",
            "-border",
            "3",
            "-bordercolor",
            "black",
            "-tile",
            f"{get_shape(total_num)}",
            str(Path(args.output_dir) / "result.jpg"),
        ],
        shell=True,
    )

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值