中心のずれた見開きスキャンPDFを2ページに分割する方法(Python,pypdf)

概要

参考書等を数ページスキャナで取り込み、タブレットに保存して、参照したいことがままある。
その際、なるべく綺麗に取り込みたいところだが、見開きでスキャンしてしまうと、以下のイメージのように、スキャンした部分でない余白部分が残ってしまう。
このように余白が残ると、非常に目障り、かつ、Acrobatを使って見開きを2ページに分割しようにも、中心がずれてしまってうまく行かない。
そこで、Pythonを使って、「余白の削除」、「2ページを1ページに分割」の両方を自動で実行するスクリプトを作成した。
使い方にコツがいるが、使いこなすととても便利なので、ぜひ使ってみてほしい。

#そのうちGUIアプリ化したいところ・・・・。

本スクリプトの使用イメージ(分割イメージ)

普通に本をスキャンするとこんなPDFになってしまう。

f:id:t_nkb:20180428182221p:plain:w500

上記のスキャンPDFにスクリプトを適応すると、以下のように二枚に分割できる!!

f:id:t_nkb:20180428183052p:plain:w500

分割方法

Pythonのインストール

本稿はまず、Python,pipがインストールされていることを前提とする。
インストールできていない方は、
「Python インストール Windows」
「pip インストール Windows」
等と検索すれば、大量に導入方法がヒットするので参考のこと。

pypdfの導入

次にPythonでPDFを扱うライブラリを導入する。
これはpipまで導入されていればコマンド一つでOK

pip install pypdf

スクリプトを実行し、PDFを切り取り、2ページに分割する

次に、以下のスクリプトを分割したいPDFファイルのある場所に、crop_pdf.pyというファイル名で保存する。
その際、
main(u"ここに分割したいPDFファイル名を入力する.pdf")
の部分に分割したいファイル名を記載しておくこと。

この状態で、

python crop_pdf.py

としてスクリプトを実行すると、output.pdfというファイル名で、分割されたPDFが出力される。

切り取り幅の調整

ただし、余白や中心位置はスキャンする方法によって千差万別なので、必ずしもピッタリ2枚に分割できるとは限らない。
その場合は、以下の値を適宜変更し、再度スクリプトを実行することで、各スキャン方法に合った分割が可能。
慣れにもよるが、分割されたPDFを見ながら2〜3回程度微調整することで、かなり満足の行く分割ができるはず。

    # 各方面の縁を削除する
    # 数値をプラスすると、mm単位で縁の余白を切り取ることができる
    bottom = 10
    top = 10
    right = 20
    left = 25

    # 左ページのセンター余白、プラスすると左ページが面積が減る(mm)
    center_left = -5
    # 右ページのセンター余白、プラスすると右ページが面積が減る(mm)
    center_right = 10

Pythonスクリプト

# -*- coding: utf-8 -*-

from pyPdf import PdfFileWriter, PdfFileReader

def main(filename):
    print "marge PDF:", filename

    output_filename = "output.pdf"

    original_L = PdfFileReader(file(filename, 'rb'))
    original_R = PdfFileReader(file(filename, 'rb'))

    marged = PdfFileWriter()

    page_num = original_L.getNumPages()

    # 各方面の縁を削除する
    # 数値をプラスすると、mm単位で縁の余白を切り取ることができる
    bottom = 10
    top = 10
    right = 20
    left = 25

    # 左ページのセンター余白、プラスすると左ページが面積が減る(mm)
    center_left = -5
    # 右ページのセンター余白、プラスすると右ページが面積が減る(mm)
    center_right = 10

    for i in xrange(0, page_num):
        # crop LEFT
        page_L = original_L.getPage(i)
        page_L.mediaBox.upperRight = (
            page_L.mediaBox.getUpperRight_x() / 2 - center_left,
            page_L.mediaBox.getUpperRight_y()-top
        )
        page_L.mediaBox.lowerLeft = (
            page_L.mediaBox.getLowerLeft_x()+left,
            page_L.mediaBox.getLowerLeft_y()+bottom
        )
        marged.addPage(page_L)


        # crop RIGHT
        page_R = original_R.getPage(i)
        page_R.mediaBox.upperRight = (
            page_R.mediaBox.getUpperRight_x()-right,
            page_R.mediaBox.getUpperRight_y()-top
        )
        page_R.mediaBox.lowerLeft = (
            page_R.mediaBox.getUpperRight_x()/2 + center_right,
            page_R.mediaBox.getLowerLeft_y()+bottom
        )
        marged.addPage(page_R)

    outputStream = file(output_filename, "wb")
    marged.write(outputStream)
    outputStream.close()


if __name__ == "__main__":
  main(u"ここに分割したいPDFファイル名を入力する.pdf")