マンガのepubのリーダーアプリとしてNeeViewを使っている。 これはepubがzipファイルであることを利用して、中の画像ファイルを表示させることで簡易的にepubリーダーになる。
ところが、これは画像ファイル名が連番であることを暗に前提としている。というのも、連番になっていないepubではページの順番が狂うのだ。
ということで、epubの画像ファイル名を連番に変換するrubyスクリプトを書いた。あまり綺麗でないが、まあ使えるだろう。
目次
使い方
- epubファイルを a.zipに名前を変更し、フォルダ名 a に展開する。
- opfファイルがあるフォルダで、このスクリプトを実行する。OEBPS か OPS のようなフォルダ内にある。
- a より上位のフォルダでMakefileを実行してepubを生成する。
epbuのフォルダ構成
epbuのフォルダ構成はたいて以下のような二つのパターンになっている:
パターンA
a/ ├── META-INF/ ├── OPS/ ├── js/ ├── mimetype └── rights.xml
パターンB
a/ ├── mimetype ├── META-INF/ └── OEBPS/
Ruby スクリプト
#!/usr/bin/env ruby
require 'pathname'
dry_run = false
ARGV.each{|opf|
# jpg, xhtmlのリストを生成
jpg_fileNameOldNew = Hash.new
xhtml_list = Array.new
File.open(opf){|f|
cnt = 0
f.each_line{|line|
if /"([^"]+\.jpg)"/i =~ line
fileNameOld1 = $1
filePathOld = Pathname(fileNameOld1)
fileNameNew = sprintf("image_%06d.jpg", cnt)
filePathNew = Pathname(filePathOld.parent + fileNameNew)
jpg_fileNameOldNew[filePathOld.to_s] = filePathNew.to_s
cnt += 1
elsif /href="([^"]+\.xhtml)"/i =~ line
# p $1
xhtml_list.push($1)
end
}
}
p jpg_fileNameOldNew # for debug
p xhtml_list # for debug
opf_old = ""
opf_new = ""
File.open(opf){|f|
opf_new = f.read
opf_old = opf_new
jpg_fileNameOldNew.each_key{|key|
if /(#{key})/ =~ opf_new
p $1
p jpg_fileNameOldNew[key]
opf_new = opf_new.gsub(/#{key}/, jpg_fileNameOldNew[key])
end
}
}
# オリジナルのopfをrenameして保存
# 書き換えたopfを保存
p opf_old # for debug
p opf_new # for debug
if !dry_run
# File.rename(opf, opf + ".orig")
File.open(opf, "w"){|f_new|
f_new.puts(opf_new)
}
end
# xhtmlの書き換え
xhtml_list.each{|xhtml|
contents_old = ""
contents_new = ""
File.open(xhtml){|f|
p f
contents_new = f.read
contents_old = contents_new # for debug
jpg_fileNameOldNew.each_key{|key|
if /(#{key})/ =~ contents_new
p $1
p jpg_fileNameOldNew[key]
contents_new = contents_new.gsub(/#{key}/, jpg_fileNameOldNew[key])
end
}
}
# オリジナルのxhtmlをrenameして保存
# 書き換えたxhtmlを保存
p contents_old # for debug
p contents_new # for debug
if !dry_run
# File.rename(xhtml, xhtml + ".orig")
File.open(xhtml, "w") {|f_new|
f_new.puts(contents_new)
}
end
}
jpg_fileNameOldNew.each_key{|key|
# jpgファイルをリネームする
orig_name = key
new_name = jpg_fileNameOldNew[key]
if !dry_run
File.rename(orig_name, new_name)
end
}
}
Makefile
この Makefile は、a/ 内の構成を見て、自動的に対象ファイルを切り替える。
EPUB_NAME = book.epub
SOURCE_DIR = a
# 検出対象ファイル・ディレクトリ
PATTERN_A = META-INF OPS js rights.xml
PATTERN_B = META-INF OEBPS
# mimetype はどちらでも共通
MIMETYPE_FILE = $(SOURCE_DIR)/mimetype
# デフォルトターゲット
all: $(EPUB_NAME)
# 条件付きでコンテンツを選択
$(EPUB_NAME): $(MIMETYPE_FILE)
@rm -f $(EPUB_NAME)
@echo "Detecting EPUB structure..."
@if [ -d "$(SOURCE_DIR)/OPS" ] && [ -d "$(SOURCE_DIR)/js" ] && [ -f "$(SOURCE_DIR)/rights.xml" ]; then \
echo "Using pattern A (OPS/js/rights.xml)"; \
cd $(SOURCE_DIR) && zip -X0 ../$(EPUB_NAME) mimetype && \
zip -Xr9D ../$(EPUB_NAME) $(PATTERN_A); \
elif [ -d "$(SOURCE_DIR)/OEBPS" ]; then \
echo "Using pattern B (OEBPS only)"; \
cd $(SOURCE_DIR) && zip -X0 ../$(EPUB_NAME) mimetype && \
zip -Xr9D ../$(EPUB_NAME) $(PATTERN_B); \
else \
echo "Error: Could not determine valid EPUB structure in '$(SOURCE_DIR)'."; \
exit 1; \
fi
@echo "EPUB created: $(EPUB_NAME)"
clean:
rm -f $(EPUB_NAME)
使用方法
- この Makefile を a/ の1つ上の階層に配置する。
- ターミナルでその階層へ移動して:
make
おまけ
Windows上のepubリーダーは、実は紀伊国屋のKinoppyがおすすめだ。 Knoppyはテキストベースのepubの縦書きに対応しており、とても使いやすい。