Разделить страницы в pdf

67

У меня есть отсканированный файл PDF, который отсканировал две страницы на одной виртуальной странице (страница в файле PDF).

Разрешение с хорошим качеством. Проблема в том, что мне приходится увеличивать изображение при чтении и перетаскивать слева направо.
Есть некоторые команды ( convert, pdftk, ...) или скрипт , который может преобразовать этот файл в формате PDF с нормальными страниц (одна страница из книги = одной страницы в PDF - файл)?

xralf
источник
1
Хотя это не самый одобренный ответ, этот действительно удивил меня. Это просто, коротко, быстро и элегантно. Я думал, что стоит упомянуть об этом здесь, так как иногда нам лень переходить к другим ответам ...
Peque
Для записей обратную операцию (объединение нескольких страниц) можно получить из командной строки (а не «печатать в файл») с pdfnupпомощью pdfjamнабора.
Скиппи ле Гран Гуру

Ответы:

46

Вот небольшой скрипт Python, использующий библиотеку PyPdf, которая делает работу аккуратно. Сохраните его в скрипте с именем un2up(или как хотите), сделайте его исполняемым ( chmod +x un2up) и запустите его как фильтр ( un2up <2up.pdf >1up.pdf).

#!/usr/bin/env python
import copy, sys
from pyPdf import PdfFileWriter, PdfFileReader
input = PdfFileReader(sys.stdin)
output = PdfFileWriter()
for p in [input.getPage(i) for i in range(0,input.getNumPages())]:
    q = copy.copy(p)
    (w, h) = p.mediaBox.upperRight
    p.mediaBox.upperRight = (w/2, h)
    q.mediaBox.upperLeft = (w/2, h)
    output.addPage(p)
    output.addPage(q)
output.write(sys.stdout)

Игнорировать любые предупреждения об устаревании; только сопровождающие PyPdf должны быть обеспокоены этим.

Если входные данные ориентированы необычным образом, вам может понадобиться использовать разные координаты при усечении страниц. См. Почему мой код неправильно разделяет каждую страницу в отсканированном PDF?


На всякий случай, если это полезно, вот мой предыдущий ответ, в котором используется комбинация двух инструментов плюс некоторое ручное вмешательство:

  • Pdfjam (по крайней мере версия 2.0) на основе пакета pdfpages LaTeX для обрезки страниц;
  • Pdftk , чтобы собрать левую и правую половинки вместе.

Оба инструмента необходимы, потому что, насколько я могу судить, pdfpages не может применить два разных преобразования к одной и той же странице в одном потоке. В вызове pdftkзамените 42 числом страниц во входном документе ( 2up.pdf).

pdfjam -o odd.pdf --trim '0cm 0cm 14.85cm 0cm' --scale 1.141 2up.pdf
pdfjam -o even.pdf --trim '14.85cm 0cm 0cm 0cm' --scale 1.141 2up.pdf
pdftk O=odd.pdf E=even.pdf cat $(i=1; while [ $i -le 42 ]; do echo O$i E$i; i=$(($i+1)); done) output all.pdf

Если у вас нет pdfjam 2.0, достаточно установить PDFLaTeX с пакетом pdfpages (в Ubuntu: вам нужны texlive-latex-рекомендуемые Установите texlive-latex-рекомендуемый и, возможно, (в Ubuntu: texlive-fonts-рекомендуемые Установить texlive-шрифты-рекомендуется ), и использовать следующий драйвер файл driver.tex:

\batchmode
\documentclass{minimal}
\usepackage{pdfpages}
\begin{document}
\includepdfmerge[trim=0cm 0cm 14.85cm 0cm,scale=1.141]{2up.pdf,-}
\includepdfmerge[trim=14.85cm 0cm 0cm 0cm,scale=1.141]{2up.pdf,-}
\end{document}

Затем выполните следующие команды, заменив 42 на количество страниц во входном файле (который должен быть вызван 2up.pdf):

pdflatex driver
pdftk driver.pdf cat $(i=1; pages=42; while [ $i -le $pages ]; do echo $i $(($pages+$i)); i=$(($i+1)); done) output 1up.pdf
Жиль "ТАК - перестань быть злым"
источник
Библиотека PyPdf работает отлично. Я только немного изменил его и запустил с помощью python conv_pdf.py res.pdf . Как бы вы запустили свой скрипт shebang из командной строки?
xralf
Я бы тоже хотел попробовать версию с pdfjam (из-за небольшого масштабирования), но после установки пакета pdfjam моя оболочка не распознает pdfjamкоманду.
xralf
@xralf: мой скрипт на python просто читает со стандартного ввода и записывает в стандартный вывод. Версия pdfjam требует pdfjam 2.0; это всего лишь небольшая оболочка для pdf-страниц, и я добавил бит LaTeX, который он генерирует, чтобы вы могли использовать его напрямую. Проблема масштабирования, вероятно, решаема с помощью pypdf, это может быть проблема размера страницы (я могу или не смогу помочь, если вы дадите больше подробностей о том, что происходит, и особенно о размерах страниц).
Жиль "ТАК - перестань быть злым"
Спасибо, разница в чуть худшем разрешении, но это не имеет значения. Я вернусь к этому, когда узнаю больше о латексе (сейчас это слишком сложно для меня, и решение действительно хорошо с PyPdf).
xralf
1
@ Жиль Верси полезный скрипт. Я ожидал увидеть что-то подобное в pdfjam, pdftk. В любом случае, некоторые люди могут захотеть, чтобы некоторые модификации разделяли страницы по другой оси и использовали другой порядок. Это возможно при изменении нескольких строк и использованияq.mediaBox.lowerRight = (w, h/2)
оны
52

Просто дополнение, так как у меня были проблемы со скриптом Python (и несколькими другими решениями): для меня это mutoolработало отлично. Это простое и небольшое дополнение поставляется с элегантным mupdfчитателем. Так что вы можете попробовать:

mutool poster -y 2 input.pdf output.pdf

Для горизонтальных расколов заменить yна x. И вы можете, конечно, объединить два для более сложных решений.

Действительно рад, что нашел это (после нескольких лет ежедневного использования mupdf :)

mutoolпоставляется с mupdf начиная с версии 1.4: http://www.mupdf.com/news


Установка mupdfи mutoolиз источника:

wget http://www.mupdf.com/downloads/mupdf-1.8-source.tar.gz
tar -xvf mupdf-1.8-source.tar.gz
cd mupdf-1.8-source
sudo make prefix=/usr/local install

Или перейдите на страницу загрузок, чтобы найти более новую версию.

Martz
источник
3
У меня был djvu ... Я превратил его в постскриптум (довольно быстро), затем в pdf (медленная черепаха) - и, наконец, mutool обрезал его так быстро, что я подумал, что это не сработало - это сработало!
Жюльен Пюйдт
2
да, мне тоже очень понравилась скорость.
Март
3
Этот самый простой и лучший. mutoolбыл сделан для этого. Кроме того, остерегайтесь -y, я думаю, что в большинстве случаев вы хотите -x.
Пятница
2
Эта утилита очень быстрая, однако у меня проблема с порядком страниц. Команда выделяет правую страницу в первой позиции и левую страницу во второй. Может кто-нибудь помочь мне с этим вопросом?
garciparedes
16

Imagemagick может сделать это за один шаг:

$ convert in.pdf -crop 50%x0 +repage out.pdf
томас
источник
1
Благодарю. Если я добавлю -density 400параметр, он будет еще лучше.
xralf
11
Похоже, что для преобразования используется растр в качестве промежуточного формата. Это приводит к размытости, даже если оригинальный PDF содержит векторные объекты.
оны
Кто-нибудь знает способ сделать это без растеризации содержимого страницы по пути ... или хотя бы установить более высокое разрешение?
Томислав Накич-Альфиревич
это переводило текст в изображения и создавало PDF из изображений. Может быть, хорошо для фотографий, но бесполезно для извлечения текста.
Андрей
6

Команда ImageMagick Convert может помочь вам обрезать ваш файл в 2 части. Смотрите http://www.imagemagick.org/Usage/crop/

Если бы я был тобой, я бы написал (shell) скрипт, подобный этому:

  1. Разделите ваш файл с помощью pdfsam : 1 страница = 1 файл на диске (Формат не имеет значения. Выберите тот, который знает ImageMagick. Я бы просто взял PS или PDF.
  2. Для каждой страницы обрежьте первую половину и поместите ее в файл с именем $ {PageNumber} A

  3. Обрежьте вторую половину и поместите ее в файл с именем $ {PageNumber} B.

    Вы получаете 1A.pdf, 1B.pdf, 2A.pdf, 2B.pdf и т. Д.

  4. Теперь соберите это снова в новом PDF. Есть много способов сделать это.
TikTak
источник
1
Не будет ли использование ImageMagick растеризовать файлы? И вы должны объяснить, что последняя часть встроена, особенно в пользу не франкоязычных в аудитории.
Жиль "ТАК - перестань быть злым"
Потому что вам не нужно понимать французский. Он просто показывает, как вы можете использовать ImageMagick для преобразования, pdftk или ghostscript (gs) в одиночку для достижения этой цели. Мне нравится использовать pdftk. Растрирование не имеет значения, так как это отсканированный документ.
Тиктак
6

Основанный на ответе от Жиля и как найти число страниц PDF, которое я написал

#!/bin/bash

pdforiginal=$1
pdfood=$pdforiginal.odd.pdf
pdfeven=$pdforiginal.even.pdf
pdfout=output_$1
margin=${2:-0}
scale=${3:-1}

pages=$(pdftk $pdforiginal dump_data | grep NumberOfPages | awk '{print $2}')

pagesize=$(pdfinfo $pdforiginal | grep "Page size" | awk '{print $5}')
margin=$(echo $pagesize/2-$margin | bc -l)

pdfjam -o $pdfood --trim "0cm 0cm ${margin}pt 0cm" --scale $scale $pdforiginal
pdfjam -o $pdfeven --trim "${margin}pt 0cm 0cm 0cm" --scale $scale  $pdforiginal

pdftk O=$pdfood E=$pdfeven cat $(i=1; while [ $i -le $pages ]; do echo O$i E$i; i=$(($i+1)); done) output $pdfout

rm $pdfood $pdfeven

Так что я могу бежать

./split.sh my.pdf 50 1.2

где 50 для корректировки поля и 1,2 для масштаба.

Антон Бессонов
источник
4

Вот вариант кода PyPDF, размещенного Жилем. Эта функция будет работать независимо от ориентации страницы:

import copy
import math
import pyPdf

def split_pages(src, dst):
    src_f = file(src, 'r+b')
    dst_f = file(dst, 'w+b')

    input = pyPdf.PdfFileReader(src_f)
    output = pyPdf.PdfFileWriter()

    for i in range(input.getNumPages()):
        p = input.getPage(i)
        q = copy.copy(p)
        q.mediaBox = copy.copy(p.mediaBox)

        x1, x2 = p.mediaBox.lowerLeft
        x3, x4 = p.mediaBox.upperRight

        x1, x2 = math.floor(x1), math.floor(x2)
        x3, x4 = math.floor(x3), math.floor(x4)
        x5, x6 = math.floor(x3/2), math.floor(x4/2)

        if x3 > x4:
            # horizontal
            p.mediaBox.upperRight = (x5, x4)
            p.mediaBox.lowerLeft = (x1, x2)

            q.mediaBox.upperRight = (x3, x4)
            q.mediaBox.lowerLeft = (x5, x2)
        else:
            # vertical
            p.mediaBox.upperRight = (x3, x4)
            p.mediaBox.lowerLeft = (x1, x6)

            q.mediaBox.upperRight = (x3, x6)
            q.mediaBox.lowerLeft = (x1, x2)

        output.addPage(p)
        output.addPage(q)

    output.write(dst_f)
    src_f.close()
    dst_f.close()
Moraes
источник
2

Лучшим решением был mutool, см. Выше:

sudo apt install mupdf-tools pdftk

раскол:

mutool poster -y 2 input.pdf output.pdf

но тогда вам нужно повернуть страницы влево:

pdftk output.pdf cat 1-endleft output rotated.pdf
Эдуард Флоринеску
источник
Все еще не перекрываются ...
MUY Бельгия
1

Основываясь на ответе Бенджамина из AskUbuntu, я бы порекомендовал использовать инструмент с графическим интерфейсом gscan2pdf .

  1. Импортируйте файл сканирования PDF в gscan2pdf. Обратите внимание, что PDF-файлы без изображений могут не работать. Сканирование в порядке, так что вам не о чем беспокоиться.

    введите описание изображения здесь

  2. Это может занять некоторое время в зависимости от размера документа. Подождите, пока он загрузится.

  3. Нажмите Ctrl + A, чтобы выбрать все страницы, а затем поверните (Ctrl + Shift + C) их, если это необходимо.

    введите описание изображения здесь

  4. Перейти в Инструменты >> Очистить . Выберите Layout как double и # output pages = 2 .

    введите описание изображения здесь

  5. Нажмите OK и дождитесь окончания работы.

    введите описание изображения здесь

  6. Сохраните файл PDF. Готово.

Нанаши Но Гомбе
источник
Проверено, не удалось со сложными документами PDF с огромным количеством изображений.
MUY Бельгия
0

Морас решение не работает для меня. Основной проблемой был расчет х5 и х6. Здесь необходимо учитывать смещение, т. Е. Если lowerLeft не равен (0,0)

Итак, вот еще один вариант с дополнительной адаптацией для использования PyPDF2 и python 3:

import copy
import math
import PyPDF2
import sys
import io 

def split_pages(src, dst):
    src_f = io.open(src, 'r+b')
    dst_f = io.open(dst, 'w+b')

    input = PyPDF2.PdfFileReader(src_f)
    output = PyPDF2.PdfFileWriter()

    for i in range(input.getNumPages()):
        p = input.getPage(i) 
        q = copy.copy(p)
        q.mediaBox = copy.copy(p.mediaBox)

        x1, x2 = p.cropBox.lowerLeft
        x3, x4 = p.cropBox.upperRight        

        x1, x2 = math.floor(x1), math.floor(x2)
        x3, x4 = math.floor(x3), math.floor(x4)

        x5 = math.floor((x3-x1) / 2 + x1)
        x6 = math.floor((x4-x2) / 2 + x2)

        if x3 > x4:        
            # horizontal
            p.mediaBox.upperRight = (x5, x4)
            p.mediaBox.lowerLeft = (x1, x2)

            q.mediaBox.upperRight = (x3, x4)
            q.mediaBox.lowerLeft = (x5, x2)
        else:
            # vertical        
            p.mediaBox.lowerLeft = (x1, x6)
            p.mediaBox.upperRight = (x3, x4)

            q.mediaBox.upperRight = (x3, x6)
            q.mediaBox.lowerLeft = (x1, x2)

        output.addPage(p)
        output.addPage(q)

    output.write(dst_f)
    src_f.close()
    dst_f.close()

if __name__ == "__main__":
    if ( len(sys.argv) != 3 ):
        print ('Usage: python3 double2single.py input.pdf output.pdf')
        sys.exit(1)

    split_pages(sys.argv[1], sys.argv[2])
Vbar
источник