背景
最近知ったのですが,中学受験にはA3対応のプリンタ/スキャナは必須だと言われているらしいです.確かにプリンタ,スキャナの使用頻度は高く,特にスキャンは面倒なのでA3/B4でできるといいなと思い,Amazonで人気のBrother MFC-6583CDWを購入しました.(品薄で,ポチってから届くまで約一ヶ月かかりました.)
今までA4とかB5の単位でスキャンしていたのが,A3とかB4の見開きでスキャンできて一見楽になったように思えましたが,印刷などを考えると見開きで1ページなのはあまり嬉しくないのでできれば見開きのページを半分に切って保存したいと思いました.
そこで,やりかたをいろいろ調べてみたのですが,意外と面倒くさそうということが分かりました.普段使っているMacだけでなくWindowsも含めてやり方のバリエーションとして調べてみたところ以下の通りいくつか見つかりましたが決め手に欠く状況でした.
- Adobe Acrobat DCを使う(mac,win) →有料
- Adobe Acrobat Reader DC + VipRiser(mac) →ファイルサイズが大きくなるらしい
- Adobe Acrobat Reader DC(win) →Adobe PDFとポスター印刷で可能だが,順番が期待通りにならないのと回転して保存ができない?
もう少し調べると,Pythonのライブラリである"PyPDF2"を使うとPDFファイルの操作ができそうということなので,ちょっと作ってみることにしました.
やりたいこと
- 普通にスキャンすると左のようになるのを,右のようにしたい
- 国語のように縦書きのものも,オプションできちんとした順番になるようにしたい
環境
- macOS: 12.4
- python: 3.9.9
- PyPDF2: 2.3.1
実装と使い方
まず,PDFを半分に切ったりするには座標系の知識が必要かと思い少し調べたところ,PDFでは左上ではなく左下が(0,0)らしいということがわかりました.図の中のx0とかy1とかはスクリプトの中に出てくる変数です.
以下のスクリプトを適当な名前(facing_page_cutter.pyなど)をつけて保存して,
-
python3 facing_page_cutter.py <filename>.pdf
もしくは実行権限(chmod u+x facing_page_cutter.py)をつけて -
/path/to/facing_page_cutter.py <filename>.pdf
とすると,実行したディレクトリに<filename>_cut.pdf
というファイルが作成されます.
縦書きの時には-v
をオプションとしてファイル名の前につけてください.
スクリプトの内容については見ていただければわかるかと思います.
#!/usr/bin/env python3
# Copyright (c) 2022, Kazuhiro FUJIHARA
import PyPDF2
from optparse import OptionParser
import sys
import re
import copy
ROTATE_ANGLE = 90
# オプションや引数の処理
usage = "usage: /path/to/%prog [options] <pdf filename w/ .pdf>"
parser = OptionParser(usage = usage)
parser.add_option("-v", "--vertical", action="store_true", dest="vertical", help="縦書き")
(options, args) = parser.parse_args()
if len(args) != 1:
parser.print_help()
sys.exit()
output_filename = re.match(r'(.*)\.pdf', args[0]).groups()[0] + '_cut.pdf'
# ファイルを開く
pdf_reader = PyPDF2.PdfFileReader(args[0])
pdf_writer = PyPDF2.PdfFileWriter()
# ページの大きさを取得する
page = pdf_reader.getPage(0)
(x0, y0) = page.mediaBox.getLowerLeft()
(x1, y1) = page.mediaBox.getUpperRight()
# 見開き1ページずつ処理をしていく
for i in range(pdf_reader.getNumPages()):
# 半分のサイズを抽出する(p1が左,p2が右のページ)
p1 = pdf_reader.getPage(i)
p2 = copy.copy(p1)
p1.cropBox.lowerLeft = (x0, y0)
p1.cropBox.upperRight = (x1, (y0 + y1) / 2)
p2.cropBox.lowerLeft = (x0, (y0 + y1) / 2)
p2.cropBox.upperRight = (x1, y1)
# 縦書きの時は右のページが先に来るようにする
if options.vertical is True:
p1, p2 = p2, p1
# 時計回りに90度回転させる
p1.rotateClockwise(ROTATE_ANGLE)
p2.rotateClockwise(ROTATE_ANGLE)
# PDFの再構成
pdf_writer.addPage(p1)
pdf_writer.addPage(p2)
# ファイルへの書き出し
with open(output_filename, mode='wb') as f:
pdf_writer.write(f)
最後に
色々試行錯誤しているときには
- macで回転
- winで分割
- macで並べ替え
とやったりしてたのですが,とりあえずこのscriptで今のところ随分楽になりました.
やっぱり楽をするための努力は惜しまないように,と思った次第です...