如何让 pdfcrop 输出所有页面具有相同的大小?

如何让 pdfcrop 输出所有页面具有相同的大小?

我正在尝试裁剪已转换为 pdf 的 powerpoint 动画以便导入到 beamer(使用 ppsplit),但当我运行pdfcrop(从 texlive)以减少空白时,它会单独裁剪页面,使得每个页面的大小都不同。有没有办法让所有页面都与最大页面的大小相同?

答案1

我发现该--verbose标志将输出每一步使用的边界框。由于这是一个“增长”动画,所以最后一页是最大的。

因此,为了使它们全部具有相同的大小,我使用 --verbose 运行了 pdfcrop 并提取了以下输出:

%%HiResBoundingBox: 48.000022 299.872046 624.124950 420.127932

然后将其输入到 pdfcrop 的第二次运行中,指定边界框:

pdfcrop --bbox "48.000022 299.872046 624.124950 420.127932" ~/animation.pdf

答案2

这是一个shshell 函数,用于将所有 pdf 页面裁剪为相同大小。该函数依赖于pdfcrop和 GNU datamash,因此请确保安装它们。

pdfconstcrop() {
    pdfcrop --bbox "$(
        pdfcrop --verbose "$@" |
        grep '^%%HiResBoundingBox: ' |
        cut -d' ' -f2- |
        LC_ALL=C datamash -t' ' min 1 min 2 max 3 max 4
    )" "$@"
}

将上面的代码块复制粘贴到您的终端中,然后只需使用pdfconstcrop而不是pdfcrop。通常的pdfcrop选项仍然有效。以下是一些示例:

  • pdfconstcrop in.pdf将结果写入in-crop.pdf
  • pdfconstcrop in.pdf out.pdf将结果写入out.pdf
  • pdfconstcrop --margins 50 in.pdf每边留出 (至少) 50pt 的边距。

答案3

如果最后一页不是最大的,我们需要计算所有页面中的最大宽度和高度,然后使用这些值来确定正确的边界框。请注意,边界框中的四个坐标是:

  • 左上角的 x 坐标(距页面左边缘的距离),
  • 左上角的 y 坐标(与页面上边缘的距离),
  • 右下角的 x 坐标(距页面左边缘的距离),
  • 右下角的 y 坐标(与页面上边缘的距离)。

可以通过对脚本进行适当的修补来计算每个页面的正确边界框并使用它们pdfcrop(它是用 Perl 编写的),但由于我不太熟悉 Perl,所以改用 Python 来编写;这里是脚本,以防它对某人有用。

import re, sys
lines = sys.stdin.readlines()
width = height = 0
# First pass: compute |width| and |height|.
for line in lines:
  m = re.match(r'\\page (\d*) \[([0-9.]*) ([0-9.]*) ([0-9.]*) ([0-9.]*)\](.*)', line, re.DOTALL)
  if m:
    page, xmin, ymin, xmax, ymax, rest = m.groups()
    width = max(width, float(xmax) - float(xmin))
    height = max(height, float(ymax) - float(ymin))
# Second pass: change bounding boxes to have width |width| and height |height|.
for line in lines:
  m = re.match(r'\\page (\d*) \[([0-9.]*) ([0-9.]*) ([0-9.]*) ([0-9.]*)\](.*)', line, re.DOTALL)
  if m:
    page, xmin, ymin, xmax, ymax, rest = m.groups()
    xmin = float(xmin)
    ymin = float(ymin)
    xmax = float(xmax)
    ymax = float(ymax)
    # We want |xmin| and |xmax| such that their difference is |width|
    addx = (width - (xmax - xmin)) / 2.0
    xmin -= addx
    xmax += addx
    # We want |ymin| and |ymax| such that their difference is |height|
    addy = (height - (ymax - ymin)) / 2.0
    ymin -= addy
    ymax += addy
    sys.stdout.write(r'\page %s [%s %s %s %s]%s' % (page, xmin, ymin, xmax, ymax, rest))
  else:
    sys.stdout.write(line)

用法:

  1. 使用 运行常规pdfcrop命令,--debug例如:

    pdfcrop --debug foo.pdf
    

    由于--debug,它不会删除它tmp-pdfcrop-*.tex创建的文件。另外,如果您向 传递了一些特殊选项,请记下pdftex它在最后执行的(或任何)命令,pdfcrop因此这并不简单。

  2. tmp-pdfcrop-*通过上面的脚本传递文件,例如:

    python find-common.py < tmp-pdfcrop-34423.tex > tmp-pdfcrop-common.tex
    

    tmp-pdfcrop-common.tex这将用不同的边界框写出。

  3. 使用此文件运行pdftex所调用的命令(或其他命令)pdfcrop

    pdftex -no-shell-escape -interaction=nonstopmode tmp-pdfcrop-common.tex
    
  4. 检查生成的 PDF 文件,并将其重命名为您喜欢的任何名称:

    mv tmp-pdfcrop-common.pdf foo-crop.pdf
    

答案4

我认为有一个 Python 包非常适合这个问题:https://github.com/abarker/pdfCropMargins

例如命令:

$ pdf-crop-margins -u -s in.pdf

裁剪in.pdf,使所有页面设置为相同大小,裁剪量在所有页面上保持一致,默认保留现有边距的 10%。输出文件与输入文件大小大致相同,并且链接和注释也保留。

相关内容