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
...
参考ページ
- Sony Readerで自炊漫画を読むよ - 機械
ChainLPを使ってSony Readerに最適化されたPDFを生成する方法が紹介されています。結合元PDFの作成はこちらを参考に。 - 指定したディレクトリ以下にだけあるディレクトリ一覧のパスを取得する - Ussy Diary
今回Dir.globを使おうと思ったらなぜかうまく行かなかったため、こちらのメソッドを使わせてもらいました。
おわりに
一つのPDFが1000ページを超えなければ、Sony Readerは自炊書籍のビューアとしてある程度快適です。移動中の暇つぶしなどにも役立ちます。