Sony Reader用にPDFを1000ページ以内で結合する

先日楽天からkoboが発売されてだいぶ話題になっていましたが、私は以前からSonyのReader(PRS-T1)を使用しています。

Sony ReaderでPDFの自炊書籍を読む場合、書籍をフォルダに分けて管理することができないため、関連するPDFを結合した方が管理しやすくなります。

ただ、Sony ReaderにはPDFのページ数が1000ページを超えたあたりからページ送りが極端に遅くなる問題があるため、PDFを結合する際はページ数に注意しなければなりません。

今回は、コマンドラインからPDFのページ数を取得するツールと、同じくコマンドラインからPDFを結合するツールを使用し、自動的に1000ページ以内でPDFを連結するスクリプトを作成してみたので紹介します。

コマンドラインからPDFのページ数を取得

Xpdf(Linux,Windowsに対応)に含まれる「pdfinfo」コマンドを使用すると、ページ数を含むPDFの情報をコマンドラインから取得することができます。

使い方はコマンドラインから以下のように実行するだけです。

> pdfinfo.exe ファイル名.pdf
    Title:          XXXXX
    Author:         XXXXX
    CreationDate:   99/99/99 99:99:99
    Tagged:         no
    Form:           none
    Pages:          999
    Encrypted:      no
    Page size:      999 x 999 pts
    File size:      99999999 bytes
    Optimized:      no
    PDF version:    9.9

コマンドラインからPDFを結合

ConcatPDF(Windowsのみ対応)を使用してコマンドラインからPDFを結合することができます。

使い方は以下のとおりです。

> ConcatPDF.exe /outfile 出力ファイル名.pdf /add-outlines 入力ファイル名_01.pdf 入力ファイル名_02.pdf 入力ファイル名_03.pdf

「/add-outlines」オプションを指定することで、入力ファイルのファイル名(拡張子除く)を見出しとして設定することができます。

自動的に1000ページ以内でPDFを結合

上記2つのコマンドを使用し、特定フォルダ配下に用意したPDFファイル群を一括処理するRubyスクリプトを作成しました。

あくまで自分用として作ったもので、実装も雑だと思いますが、誰かの参考になるかもしれないので載せておきます。なお、使用は自己責任でお願いします。

# coding: utf-8

require 'nkf'

Encoding.default_internal = 'UTF-8'

BASE_DIR = 'C:/path/to/base dir/'
BOOKS_DIR = '01.個別PDF'
OUTPUT_DIR = '02.連結PDF'
Dir.chdir(BASE_DIR)

def directories(path)
  Dir.entries(path).map do |f|
    expand_path = File.expand_path(f, path)
    expand_path if File.directory?(expand_path)
  end[2..-1].delete_if {|v| v.nil?}
end

def files(path)
  Dir.entries(path).map do |f|
    expand_path = File.expand_path(f, path)
    expand_path if File.file?(expand_path)
  end[2..-1].delete_if {|v| v.nil?}
end

def concatpdf(pdfs, book_dir, book_count_s, book_count_e)
  book_range = ""
  if pdfs.length > 1 then
    book_range = '(' + sprintf("%02d", book_count_s) + '-' + sprintf("%02d", book_count_e) + ')'
  else
    book_range = '(' + sprintf("%02d", book_count_e) + ')'
  end
  output_filename = OUTPUT_DIR + '/' + File.basename(book_dir) + book_range + '.pdf'
  concatpdf_cmd = %Q<"C:/path/to/ConcatPDF.exe" /outfile "#{output_filename}" /add-outlines "#{pdfs.join("\" \"")}">
  print "  " + File.basename(output_filename) + " ..."
  if system(NKF.nkf('-s', concatpdf_cmd)) then
    print "OK\n"
  end
end

directories(File.expand_path(BOOKS_DIR, BASE_DIR)).each do |book_dir|
  puts "対象: " + File.basename(book_dir)
  book_count_s = 1
  book_count_e = 0
  page_count = 0
  pdfs = []
  files(File.expand_path(book_dir, BASE_DIR)).each do |pdf|
    page_count += `C:/path/to/pdfinfo.exe "#{NKF.nkf('-s', pdf)}"`.sub(/.*^Pages:\s+(\d+).*/m, '\1').to_i
    if page_count < 1000 then
      pdfs << pdf.sub(/^#{BASE_DIR}/, '')
      book_count_e += 1
    else
      concatpdf(pdfs, book_dir, book_count_s, book_count_e)
      book_count_s = book_count_e + 1
      page_count = 0
      pdfs = []
      redo
    end
  end
  if pdfs != [] then
    concatpdf(pdfs, book_dir, book_count_s, book_count_e)
  end
end

PDFファイルは以下のように配置することを想定しています。

BASE_DIR/
  01.個別PDF/
    タイトル1 全XX巻/
      タイトル1 第01巻.pdf
      タイトル1 第02巻.pdf
      ...
    タイトル2 全XX巻/
      タイトル2 第01巻.pdf
      タイトル2 第02巻.pdf
      ...
  02.連結PDF/
    タイトル1 全XX巻(01-XX).pdf
    タイトル1 全XX巻(YY-ZZ).pdf
    タイトル2 全XX巻(01-XX).pdf
    ...

参考ページ

おわりに

一つのPDFが1000ページを超えなければ、Sony Readerは自炊書籍のビューアとしてある程度快適です。移動中の暇つぶしなどにも役立ちます。

blog comments powered by Disqus