Как сделать так, чтобы pdfcrop выводил все страницы одинакового размера?

Как сделать так, чтобы pdfcrop выводил все страницы одинакового размера?

Я пытаюсь обрезать анимацию PowerPoint, которую я преобразовал в PDF для импорта в Beamer (используя ppsplit), но когда я запускаю pdfcrop(из texlive) для уменьшения пробелов, он обрезает страницы по отдельности, так что каждая страница имеет разный размер. Есть ли способ сделать так, чтобы все страницы были того же размера, что и самая большая страница?

решение1

Я обнаружил, что --verboseфлаг выводит ограничивающую рамку, используемую на каждом шаге. Поскольку это была «растущая» анимация, последняя страница самая большая.

Поэтому, чтобы получить все файлы одинакового размера, я запустил pdfcrop с параметром --verbose и извлек следующий вывод:

%%HiResBoundingBox: 48.000022 299.872046 624.124950 420.127932

а затем передал это во второй запуск pdfcrop, указав ограничивающую рамку:

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

решение2

Вот shфункция оболочки для обрезки всех страниц 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оставляет поля (не менее) 50 пунктов с каждой стороны.

решение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% существующих полей. Выходной файл примерно того же размера, что и входной файл, а также ссылки и аннотации сохраняются.

Связанный контент