本履歴

購入した古本の履歴と時々プログラミング

製本のためPDFをbookletページに変換

今度引っ越すのだが、以前購入したクリームキンマリという紙が余っていることに気づいたので、なにか製本しようかなと考えた。
英語の練習用に半年間くらい購読していたESL PodcastのPDFが多量にあるので、それを製本してみたいかなと。通常kindle上でESLのpdfを読んでいるが、辞書機能は便利だけど、画面が小さくて紙に比べると可読性は格段に落ちる。また最初のGlossaryに移動とかも手間取ってしまう。
20エピソードでだいたい190−200ページ。折丁一つで紙4枚16ページなので、12折丁くらいの計算。
ただ、そのままA4に両面2ページ集約で印刷しても、通常うまくいかない。というのも、プリンターは1,2,3,4ページと印刷していくので、2,15,16,1というように印刷してくれないと折丁として機能しないのだ。その機能がプリンタに備わっていればいいのにと常々思っていたのだが、家庭用のプリンタにはどうやらないようだ。
そこで、自分でプログラムを組んで、PDF自体のページをBooklet用にソートして出力することにした。
必要な機能は、

  1. 複数のPDFを一つのPDFに集約
  2. その際、ページの順番をn枚の折丁にフィットするように整列
  3. 全ページ数が4*nで余る場合は、最後にブランクのページを追加
  4. A4をA5に縮小することになるので、余白はなるべくカット

RubygemsOrigami(http://esec-lab.sogeti.com/pages/Origami)というPDFを操作するものがあったのでこれを使ってみた。
ちなみにPDFにはMediaBox(http://dtpwiki.jp/?PDF)というページの台紙を指定するプロパティがあるので、それでブランクページのサイズを指定した。後で余白をカットすることになるので、あまり意味はないのだが。

#!ruby2.0
require "origami"
include Origami

start_page_no=841
end_page_no=860

#n...number of leave, e.g. n=4 -->A folio has 16 pages
#if pages.size mod 4*n has remainder then fill blank pages at last position
def booklet_sort(pages,n)
  blank_page=copy_blank_pages_from(pages.first)
  ret=[]
  folio_size=4*n
  until pages.empty?
    sheets=folio_size.times.map{pages.shift}
    folio=[]
    n.times{
      # 1   16
      #---*---
      # 2   15
      #-->2,15,16,1
      #you have to change the sheet order in order to fit your printer.
      p1=sheets.shift
      p2=sheets.shift
      p16=sheets.pop
      p15=sheets.pop
      folio << p2 << p15 << p16 << p1
    }
    folio.each{|page|ret << (page ? page : blank_page)}
  end
  ret
end

def copy_blank_pages_from(page)
  blank_page=Page.new
  blank_page.setMediaBox(page.MediaBox)
  blank_page
end

#merge pages in all pdf files
def all_pages(file_names)
  pages=[]
    file_names.each{|file_name|
      pdf=PDF.read(file_name)
      pdf.each_page{|page|pages << page}
    }
  pages
end

def generate_files(prefix,range,n,postfix)
  range.map{|num|prefix+("%0#{n}d"%num)+postfix}
end

file_names=generate_files("../#{start_page_no}-#{end_page_no}/ESLPod_",
  start_page_no..end_page_no,3,"_Guide.pdf")
pages=all_pages(file_names)
folios=booklet_sort(pages,4)

pdf=PDF.new
folios.each{|page|pdf.append_page(page)}
pdf.save("esl_booklet_#{start_page_no}-#{end_page_no}.pdf")

次に、集約したPDFの余白があまりに大きいので、pdfscissors(http://www.pdfscissors.com/)でカット。素晴らしいツールだなあ。
なぜか複数のpdfファイルマージするとファイルサイズが膨れ上がるのだが、原因はよくわかっていない。
最後に、あとは印刷して好きなように製本してみてね。チャオ!

後日、製本した画像をあげようっと。