Chia trang bằng pdf


67

Tôi có một tệp pdf được quét đã quét hai trang trên một trang ảo (trang trong tệp pdf).

Độ phân giải là với chất lượng tốt. Vấn đề là tôi phải phóng to khi đọc và kéo từ trái sang phải.
Có một số lệnh ( convert,, pdftk...) hoặc tập lệnh có thể chuyển đổi tệp pdf này với các trang bình thường (một trang từ sách = một trang trong tệp pdf) không?


1
Mặc dù nó không phải là câu trả lời được đánh giá cao nhất, nhưng điều này thực sự làm tôi ngạc nhiên. Nó là đơn giản, ngắn, nhanh chóng và thanh lịch. Tôi nghĩ rằng nó đáng để đề cập đến nó ở đây, vì đôi khi chúng ta quá lười biếng để cuộn xuống các câu trả lời khác ...
Peque

Đối với các bản ghi, thao tác ngược (nối nhiều trang) có thể được lấy từ dòng lệnh (thay vì "in ra tệp") với pdfnup, từ pdfjambộ.
Skippy le Grand Gourou

Câu trả lời:


46

Đây là một tập lệnh Python nhỏ sử dụng thư viện PyPdf thực hiện công việc một cách gọn gàng. Lưu nó trong một tập lệnh được gọi là un2up(hoặc bất cứ điều gì bạn thích), làm cho nó có thể thực thi được ( chmod +x un2up) và chạy nó dưới dạng bộ lọc ( 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)

Bỏ qua bất kỳ cảnh báo khấu hao; chỉ những người duy trì PyPdf cần quan tâm đến những người đó.

Nếu đầu vào được định hướng theo một cách khác thường, bạn có thể cần phải sử dụng các tọa độ khác nhau khi cắt ngắn các trang. Xem tại sao mã của tôi không phân chia chính xác từng trang trong pdf được quét?


Trong trường hợp nó hữu ích, đây là câu trả lời trước đây của tôi sử dụng kết hợp hai công cụ cộng với một số can thiệp thủ công:

  • Pdfjam (ít nhất là phiên bản 2.0), dựa trên gói LaTeX pdf , để cắt các trang;
  • Pdftk , để đặt nửa trái và phải trở lại với nhau.

Cả hai công cụ đều cần thiết vì theo như tôi có thể nói các trang pdf không thể áp dụng hai biến đổi khác nhau cho cùng một trang trong một luồng. Trong lệnh gọi đến pdftk, thay thế 42 bằng số trang trong tài liệu đầu vào ( 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

Trong trường hợp bạn không có pdfjam 2.0, thì cài đặt PDFLaTeX là đủ với gói pdfpages (trên Ubuntu: bạn cần texlive-latex-khuyên Cài đặt texlive-latex-khuyên và có lẽ (trên Ubuntu: khuyên dùng texlive-phông chữ Cài đặt texlive-phông chữ-đề nghị ) và sử dụng trình điều khiển sau tập tin 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}

Sau đó chạy các lệnh sau, thay thế 42 bằng số trang trong tệp đầu vào (phải được gọi 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

Thư viện PyPdf hoạt động hoàn hảo. Tôi chỉ thay đổi nó một chút và chạy nó với python conv_pdf.py res.pdf . Làm thế nào bạn sẽ chạy tập lệnh shebang của bạn từ dòng lệnh?
xralf

Tôi cũng muốn dùng thử phiên bản với pdfjam (vì tỷ lệ nhỏ), nhưng sau khi cài đặt gói pdfjam, shell của tôi sẽ không nhận ra pdfjamlệnh.
xralf

@xralf: Kịch bản python của tôi chỉ đọc từ đầu vào tiêu chuẩn và ghi vào đầu ra tiêu chuẩn. Phiên bản pdfjam yêu cầu pdfjam 2.0; nó chỉ là một trình bao bọc nhỏ xung quanh các trang pdf và tôi đã thêm một chút LaTeX mà nó tạo ra để bạn có thể sử dụng trực tiếp. Vấn đề mở rộng có thể giải quyết được với pypdf, đây có thể là vấn đề kích thước trang (tôi có thể hoặc không thể giúp nếu bạn cung cấp thêm chi tiết về những gì đang xảy ra và đặc biệt là kích thước trang có liên quan).
Gilles

Cảm ơn bạn, sự khác biệt là ở độ phân giải kém hơn một chút, nhưng điều này không thành vấn đề. Tôi sẽ quay lại với nó khi tôi biết nhiều hơn về latex (hiện tại nó quá phức tạp đối với tôi và giải pháp thực sự tốt với PyPdf).
xralf

1
@Gilles Versy kịch bản hữu ích. Tôi đã dự kiến ​​sẽ thấy một cái gì đó như thế trong pdfjam, pdftk. Dù sao, một số người có thể muốn một số sửa đổi để phân chia các trang trên trục khác và sử dụng thứ tự khác nhau. Điều này có thể với việc thay đổi một vài dòng và sử dụngq.mediaBox.lowerRight = (w, h/2)
ony

52

Chỉ là một bổ sung vì tôi có vấn đề với kịch bản python (và một số giải pháp khác): đối với tôi mutoolđã làm việc rất tốt. Đó là một bổ sung đơn giản và nhỏ được gửi với mupdfngười đọc thanh lịch . Vì vậy, bạn có thể thử:

mutool poster -y 2 input.pdf output.pdf

Đối với phân chia ngang, thay thế ybằng x. Và tất nhiên, bạn có thể kết hợp cả hai cho các giải pháp phức tạp hơn.

Thực sự hạnh phúc khi tìm thấy điều này (sau nhiều năm sử dụng mupdf hàng ngày :)

mutoolđược vận chuyển với mupdf bắt đầu từ phiên bản 1.4: http://www.mupdf.com/news


Cài đặt mupdfmutooltừ nguồn:

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

Hoặc vào trang tải xuống để tìm phiên bản mới hơn.


3
Tôi đã có một djvu ... Tôi đã biến nó thành một phần tái bút (khá nhanh), sau đó thành pdf (rùa chậm) - và cuối cùng mutool cắt nó nhanh đến mức tôi nghĩ rằng nó không hoạt động - nó đã có!
Julien Puydt

2
vâng, tôi cũng rất hài lòng với tốc độ
martz

3
Điều này là dễ nhất và tốt hơn. mutoolđã được thực hiện cho điều này. Ngoài ra, hãy cẩn thận -y, tôi nghĩ trong hầu hết các trường hợp những gì bạn muốn là -x.
fiatjaf

2
Tiện ích này rất nhanh, tuy nhiên tôi có vấn đề với thứ tự trang. Lệnh phân bổ trang bên phải ở vị trí đầu tiên và trang bên trái ở vị trí thứ hai. Ai đó có thể giúp tôi với vấn đề này?
garciparedes

1
@garciparedes unix.stackexchange.com/questions/184799/ triệt
Không ai

16

Imagemagick có thể làm điều đó trong một bước:

$ convert in.pdf -crop 50%x0 +repage out.pdf

1
Cảm ơn. Nếu tôi thêm -density 400tham số thì nó thậm chí còn có chất lượng tốt hơn.
xralf

11
Có vẻ như convert sử dụng raster như một định dạng trung gian. Điều đó gây ra cái nhìn mờ ngay cả khi PDF gốc chứa các đối tượng vector.
ony

Có ai biết cách để làm điều này mà không cần raster nội dung trang trên đường đi ... hoặc ít nhất là để đặt độ phân giải cao hơn không?
Tomislav Nakic-Alfirevic

điều này khiến văn bản thành hình ảnh và tạo pdf từ hình ảnh. Có thể tốt đẹp cho các bức ảnh nhưng vô dụng để trích xuất văn bản.
andrej

6

Lệnh Convert của ImageMagick có thể giúp bạn cắt tập tin của bạn thành 2 phần. Xem http://www.imagemagick.org/Usage/crop/

Nếu tôi là bạn, tôi sẽ viết một kịch bản (shell) như thế này:

  1. Tách tệp của bạn bằng pdfsam : 1 trang = 1 tệp trên đĩa (Định dạng không thành vấn đề. Chọn một tệp mà ImageMagick biết. Tôi chỉ cần lấy PS hoặc PDF.
  2. Đối với mỗi trang, hãy cắt nửa đầu và đặt nó vào một tệp có tên $ {PageNumber} A

  3. Cắt nửa thứ hai và đặt nó vào một tệp có tên $ {PageNumber} B.

    Bạn nhận được 1A.pdf, 1B.pdf, 2A.pdf, 2B.pdf, v.v.

  4. Bây giờ, lắp ráp lại trong một PDF mới. Có nhiều phương pháp để làm điều này.

1
Sẽ không sử dụng ImageMagick rasterize các tập tin? Và bạn nên giải thích rằng phần cuối cùng nội tuyến, đặc biệt là vì lợi ích của các phi francophones trong khán giả.
Gilles

Bởi vì bạn không cần phải hiểu tiếng Pháp. Nó chỉ cho thấy cách bạn có thể sử dụng chuyển đổi, pdftk hoặc ghostscript (gs) của ImageMagick một mình để đạt được mục tiêu này. Tôi thích sử dụng pdftk. "Rastering" không thành vấn đề vì đây là tài liệu được quét.
tiktak

6

Dựa trên câu trả lời từ Gillescách tìm số trang PDF tôi đã viết

#!/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

Để tôi có thể chạy

./split.sh my.pdf 50 1.2

trong đó 50 cho điều chỉnh lề và 1,2 cho tỷ lệ.


4

Đây là một biến thể của mã PyPDF được đăng bởi Gilles. Chức năng này sẽ hoạt động bất kể định hướng trang là gì:

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

Giải pháp tốt nhất là mutool xem ở trên:

sudo apt install mupdf-tools pdftk

chia:

mutool poster -y 2 input.pdf output.pdf

nhưng sau đó bạn cần xoay các trang bên trái:

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

Vẫn không có sự trùng lặp ...
MUY Bỉ

1

Dựa trên câu trả lời của Benjamin tại AskUbfox, tôi sẽ khuyên bạn nên sử dụng công cụ GUI có tên gscan2pdf .

  1. Nhập tệp quét PDF vào gscan2pdf. Lưu ý rằng các tệp PDF không phải hình ảnh có thể không hoạt động. Quét vẫn ổn, vì vậy bạn không phải lo lắng.

    nhập mô tả hình ảnh ở đây

  2. Nó có thể mất một lúc tùy thuộc vào kích thước của tài liệu. Đợi đến khi nó tải lên.

  3. Nhấn Ctrl + A để chọn tất cả các trang và sau đó xoay (Ctrl + Shift + C) chúng nếu cần.

    nhập mô tả hình ảnh ở đây

  4. Chuyển đến Công cụ >> Dọn dẹp . Chọn Bố cụcgấp đôi# trang đầu ra = 2 .

    nhập mô tả hình ảnh ở đây

  5. Nhấn OK và đợi cho đến khi công việc kết thúc.

    nhập mô tả hình ảnh ở đây

  6. Lưu tệp PDF. Làm xong.


Đã thử nghiệm, thất bại với các tài liệu pdf phức tạp với một lượng lớn hình ảnh.
MUY Bỉ

0

giải pháp moraes không làm việc cho tôi. Vấn đề chính là tính toán x5 và x6. Ở đây một phần bù phải được xem xét, tức là nếu lowLeft không ở (0,0)

Vì vậy, đây là một biến thể khác, với sự thích ứng bổ sung để sử dụng PyPDF2 và 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])
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.