Розділити сторінки у форматі PDF


67

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

Дозвіл хорошої якості. Проблема в тому, що я маю масштабувати під час читання та перетягувати зліва направо.
Є деякі команди ( convert, pdftk, ...) або скрипт , який може перетворити цей файл у форматі PDF з нормальними сторінок (одна сторінка з книги = однієї сторінки в PDF - файл)?


1
Хоча це не найвигідніша відповідь, ця дійсно мене здивувала. Це просто, коротко, швидко та елегантно. Я подумав, що варто згадати це тут, оскільки іноді ми лінуємося прокручувати вниз до інших відповідей ...
Peque

Для записів, зворотна операція (приєднання декількох сторінок) може бути отримати з командного рядка (а не «друк в файл») з pdfnup, з pdfjamпочту.
Skippy le Grand Gourou

Відповіді:


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) на основі пакету pdfсторінок 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-латекс Рекомендується встановлювати texlive-латекс і, можливо, (на 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
@Gilles Versy корисний сценарій. Я очікував побачити щось подібне в 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

Або перейдіть на сторінку завантажень, щоб знайти нову версію.


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-зображення із зображень. Може бути приємним для фотографій, але марним для вилучення тексту.
andrej

6

Команда «Перетворити ImageMagick» може допомогти вам обрізати файл у 2 частинах. Дивіться http://www.imagemagick.org/Usage/crop/

Якби я був ти, я написав би такий сценарій (оболонку):

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

  3. Обріжте другу половину і поставте її у файл під назвою $ {PageNumber} B.

    Ви отримуєте 1A.pdf, 1B.pdf, 2A.pdf, 2B.pdf тощо.

  4. Тепер зібрати це ще раз у новому PDF-файлі. Для цього існує багато методів.

1
Чи не використовуючи ImageMagick розпарити файли? І ви повинні пояснити цю останню частину в ролику, особливо на користь не франкофонів у аудиторії.
Жиль

Тому що вам не потрібно розуміти французьку мову. Він просто показує, як ви можете використовувати конвертувати, pdftk або ghostscript (gs) ImageMagick поодинці для досягнення цієї мети. Мені подобається використовувати pdftk. "Растеринг" не має значення, оскільки це відсканований документ.
тиктак

6

На основі відповіді від Gilles та того, як знайти кількість написаних нами сторінок 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()

2

Найкращим рішенням був мутоол див. Вище:

sudo apt install mupdf-tools pdftk

розкол:

mutool poster -y 2 input.pdf output.pdf

але тоді потрібно повернути сторінки вліво:

pdftk output.pdf cat 1-endleft output rotated.pdf

Все ще немає перекриттів ...
МУЙ Бельгія

1

Виходячи з відповіді Бенджаміна в AskUbuntu, я рекомендував би використовувати інструмент GUI під назвою gscan2pdf .

  1. Імпортуйте файл сканування PDF у gscan2pdf. Зверніть увагу, що PDF-файли без зображення можуть не працювати. Сканування чудово, тому вам не доведеться хвилюватися.

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

  2. Це може зайняти деякий час, залежно від розміру документа. Зачекайте, поки він завантажиться.

  3. Натисніть Ctrl + A, щоб вибрати всі сторінки, а потім оберніть їх (Ctrl + Shift + C), якщо необхідно.

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

  4. Перейдіть до Інструменти >> Очищення . Виберіть " Макет" як подвійний і # вихідний сторінки = 2 .

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

  5. Натисніть ОК і зачекайте, поки робота закінчена.

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

  6. Збережіть файл PDF. Зроблено.


Випробуваний, не вдався до складних PDF-документів із величезним числом зображень.
МУП Бельгія

0

рішення мурасу для мене не спрацювало. Основною проблемою був розрахунок x5 та x6. Тут слід враховувати зміщення, тобто якщо нижня ліва відстань не дорівнює (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])
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.