Как мне обрезать страницы 3 и 4 в многостраничном PDF с использованием ghostscript
Я хотел бы обрезать только некоторые страницы в многостраничном PDF, сохраняя все страницы, некоторые обрезанные, другие нет. Я попробовал следующее, но он "удаляет" не обрезанные страницы...
gswin64.exe -o cropped.pdf -sDEVICE=pdfwrite -dFirstPage=3 -dLastPage=4 -c "[/CropBox [24 72 1559 1794]" -c " /PAGES pdfmark" -f input.pdf
Я видел сообщения о различных кадрированиях на нечетных и четных страницах, но я не мог понять, как применить это к определенной странице в многостраничном документе.
gswin64.exe -o cropped.pdf -sDEVICE=pdfwrite -c "<</EndPage {0 eq {2 mod 0 eq {[/CropBox [0 0 1612 1792] /PAGE pdfmark true}{[/CropBox [500 500 612 792] /PAGE pdfmark true} ifelse}{false}ifelse}>> setpagedevice" -f input.pdf
Это обрезает все страницы в соответствии с настройками второго CropBox. Если кто-то задается вопросом о больших полях... Я применяю это сделать большие рисунки. Я также пытался заменить некоторые операторы, чтобы применить обрезку только к определенному номеру страницы: "sub 4" вместо "2 mod" была одной попыткой достичь условия " 0 eq" только тогда, когда текущий номер страницы достигнет 4.
1 ответ
ОК, во-первых, Ghostscript и устройство pdfwrite не "модифицируют" входной PDF-файл. Для постоянных читателей; стандартная лекция здесь, если вы прочитали ее раньше, можете пропустить следующий абзац.
Это работает так, что входной файл полностью интерпретируется в виде последовательности графических примитивов, которые отправляются на устройство. Устройства рендеринга затем вызывают графическую библиотеку для рендеринга примитивов в растровое изображение, которое затем выводится. Высокоуровневые (векторные) устройства, такие как pdfwrite, переводят примитивы в эквивалентные операции на некотором языке описания страниц высокого уровня и генерируют его.
Таким образом, когда вы выбираете -dFirstPage и -dLastPage, это только страницы входного файла, который вы выбираете для обработки. Таким образом, pdfwrite не "удаляет" ваши страницы, вы никогда не отправляли их на устройство.
Теперь Ghostscript является интерпретатором PostScript, и поэтому на его действие могут влиять написание программ на PostScript. В вашем случае вы, вероятно, захотите обработать все страницы (так что опустите -dFirstPage и -dLastPage), но пишите pdfmark только на выбранных страницах.
Это можно сделать с помощью процедуры BeginPage или EndPage. Если вы ищете здесь или в теге PostScript, вы найдете несколько примеров. По сути, обе процедуры до сих пор вызываются с кодом причины и количеством страниц.
Из памяти вы захотите проверить, что код причины равен 2. Если это так, то вы хотите проверить количество страниц, и если оно соответствует вашим критериям (в данном случае, количество равно 3 или 4), выполните /PAGE pdfmark. В любом случае вы хотите вернуть 'true', чтобы страница была выброшена.
[РЕДАКТИРОВАТЬ добавлено здесь]
Хм, хорошо, я вижу проблему. Происходит то, что интерпретатор PDF вызывает 'setpagedevice', чтобы установить размер страницы для каждой страницы, в случае, если размер страницы изменился. Проблема в том, что это сбрасывает счетчик страниц до 0 каждый раз.
Теперь я бы обычно не предлагал следующее, потому что оно опирается на некоторые недокументированные аспекты интерпретатора PDF Ghostscript. Однако я случайно узнал, что интерпретатор PDF отслеживает номер страницы внутри, используя именованный объект с именем /Page#.
Итак, если я возьму код, который вы написали, и слегка его изменим:
<<
/EndPage {
0 eq {
pop /Page# where {
/Page# get
3 eq {
(page 3) == flush
[/CropBox [0 0 1612 1792] /PAGE pdfmark
true
}
{
(not page 3) == flush
[/CropBox [500 500 612 792] /PAGE pdfmark
true
} ifelse
}{
true
} ifelse
}
{
false
}
ifelse
}
>> setpagedevice
Несколько вещей, чтобы отметить; там есть некоторая отладка, строки с == flush распечатывают некоторые вещи на обратном канале, чтобы вы знали, как обрабатывается каждая страница. Если / Page # не определен, то код просто оставляет все в покое, это всего лишь некоторые базовые вещи для обеспечения безопасности.
Вместо того, чтобы вводить все это в командной строке (которая также теряет отступы и плохо читается), я вставил ее в файл с именем test.ps, а затем вызвал GS как:
gswin32c -sDEVICE=pdfwrite -sOutputFile=out.pdf test.ps input.pdf
Это не самое лучшее решение в мире, но оно работает для меня.