青空文庫のルビや傍点をHTMLタグに変換

小ネタ。
青空文庫形式で書かれたテキストをちょっといじる機会があったんで、例によってperlでごそごそと。
『青空文庫 組版案内』(http://kumihan.aozora.gr.jp)に詳細な資料や、青空記法で書かれたテキストをXHTMLに変換するrubyのスクリプトも提供されている。
青空文庫からXHTMLへはrubyのスクリプトを使わせてもらえばそれで解決なんだけど、用途・前提が青空文庫。当然ながら青空文庫用のcssが埋めこまれる。
電子書籍にするのにそのままでは使えない。
本文で青空記法が使われてるのはルビと傍点、太字程度だったので、その3つをHTMLのタグに変換するスクリプトをでっち上げ。
use strict;
use utf8;
use Encode;
my $emphasis = sub {
my ($w, $t, $tag) = @_;
$w = substr($w, 0, length($w) - length($t));
if($tag eq ’sesami’){
return $w . ’<span class="sesami">’ . $t . ’</span>’;
}
elsif($tag eq ’bold’){
return $w . ’<span style="font-weight:bold">’ . $t . ’</span>’;
}
};
while(<>){
my $line = Encode::decode(’shiftjis’, $_);
$line =~ s!([^[]+)[#「([^」]+)」に傍点]!$emphasis->($1, $2, ’sesami’)!eg;
$line =~ s[#傍点終わり]!<span class="sesami">$1</span>!g;
$line =~ s!([^[]+)[#「([^」]+)」は太字]!$emphasis->($1, $2, ’bold’)!eg;
$line =~ s[#太字終わり]!<span style="font-weight:bold;">$1</span>!g;
$line =~ s![ \||]?([\p{InCJKUnifiedIdeographs}\x{3005}]+[\p{InHiragana}\p{InKatakana}]*)《([\p{InHiragana}\p{InKatakana}]+)》!<ruby>$1<rt>$2</rt></ruby>!g;
$line =~ s!―!─!g;
$line =~ s![(#|*)[^]]+]!!g;
print Encode::encode(’utf8’, $line);
}
perlのスクリプト的には、漢字かななどの判定にUnicodeブロックが便利でおすすめ。
無名サブルーチンも便利。
意外なところで青空記法が使われててちょっとびっくりだった。
テキストデータ利用ということで、ボランティアさんが入力するのに青空記法はわかりやすくていいんだろうなあ。
青空EPUBの現バージョン3-1.1.0b45はepubcheckでエラーになる。
原因はnav.xhtmlのlandmark部、「Undefined property:title-page」で、ここを「titlepage」にすれば大丈夫。

自転車置き場の新顔…のわりに態度がデカイ。
サンプルの縦書き段組表示

やっとFirefoxが縦書きに対応したことで、すべてのブラウザで縦書きでの表示ができるようなった。
今までは、「サンプルを読む」みたいなリンクをクリックすると、Firefoxの場合は横書き、それ以外のブラウザは縦書きのポップアップウィンドウを表示させていた。苦肉の策。
今後はブラウザ判定して分岐させる必要がなくなったので、以前やってたようにページに縦書き段組のサンプルをajaxで埋め込む方法に変更した。
(とはいえ、新しいバージョンが出たからといってみんなすぐにインストールするとも思えないので、しばらくは必要だと思うけど)
ajaxにしたのは。
サンプルはそれなりに多いんで、ページ表示がひょっとして遅くなっちゃいけないと思ったから。
サンプル以外の表紙やキャッチなんかのいわゆる書誌情報は、とっとと表示してもらいたいということ。WEBで唯一断言できるのが「速さは正義」だ。表示にもたもたしてたらそれだけでそのページは終了だ。
ajaxならまずページは先に表示されるので、体感的なページ表示速度に影響しない。
縦書きのポップアップを使わなかったのは。
クリックはコストが高いから。
以前にも書いたかもしれないけど、オンデマンドの動画配信サイトで仕事をしていた頃に何度も(毎日)計測していた。ほとんどのユーザーはランディングページ→離脱。
いや、楽天のチラシのようなフンドシのような長いページをダセエーと思ってるけど、あれは正しい。
ユーザーのクリック誘導がいかに大変かという結果。理由もなくあんなクソみたいなページ構成にしてるわけじゃない、てことだと思う。
また、WEBページで、ページを縦にスクロールしていって、サンプルの縦書きのコンテンツだけ横にスクロールというのは違和感がある、目線の動きとUI的にありえない。
縦書きの文章は段組されて、目線の流れ的に、右上から左に読んで行って、左下端にきたら、下の段の右上端から読むものだ。
てことで(表示速度のリスクとクリックコストと縦横混在混乱を検討して)、縦書き段組を復活させた。
(のはいいけど、Safari、ChromeはともかくIE(ver.10)がまたCSSの解釈が微妙に違ってるぽいなあ)
もちろん不満点はあって。
とにかくWindowsはフォントが汚いんでビックリ。
ディスプレイの設定でマシになるとのことだけど、そんなことを来訪するユーザーに強要するわけにはいかない(昭和のホームページでは「画面1024px以上推奨」とか「フォントサイズ12px推奨」とかあったけど)
ダッシュが繋ってくれない。
これは電子書籍でも苦労してるところだからしょうがないか。
ただ、WEBというかブラウザにあまり多くを求めてもしょうがないんで、現状はこれでOK。
電子書籍を読むなら、それに特化した専用端末か専用アプリを利用するし。
この雑記帖を「縦書き」で検索するとどっさりヒット。2009年とか2004年ぐらいから待望の縦書き実現、というやつ。
やっと、Firefoxありがとう、だ。

日野裕太郎の作品紹介ページでサンプルが読めるのでゼヒゼヒ!!
↓このへんからどうぞ
作品の寿命

なるほどなあ、そういう考えかたもありかもしれんなあ、という微温い小ネタ。
本を書いて出版するからには、読者に届いてその作品をずっと愛でられていたい・大切にしてもらいたい、というものばかりだと思ってたし、実際、底辺とはいえ出版社で編集をやってた頃の作家さんは例外なくその通りだった。
でも、そうじゃないこともあって、ちょっと驚いた。
・本を買ってもらって、読んでもらったら、本はその場で消えてなくなってほしい。
・わたしが死んだら、わたしの出した本はすべて燃えて消えてほしい。
なんでやねん、と聞いてみたらば「だって気持ち悪いじゃないですか」と。
いつまでも自分の文章や絵が残ることが気持ち悪いということだろうか。
でも、なんかわかるような気がした。黒歴史の積み上げというか…とか言うと叱られそうだけど。
あるいは、その時、思いが伝われば良くて、カタチはいらないというか。
もしくは、古い自分の作品は、今の自分から見ると完成度が、とか(そういや、再録や単行本化で古い作品を引っ張り出して見せると、これまたほぼ例外なく、ヤメテ!見せないで!という悲鳴があがった)
なので、みんながみんな、自分の書いたもの発表したもの出版したものについて、同じ思いではないということも少しは意識しておきたいかなあ、と思ったしだい(今さら)

風物詩:電子書籍は信用できない

とらのあなのダウンロードストアが終了したらしい。
DRMのかかった閲覧認証が必要な本は読めなくなる。またかというネタなんだけど、DRMでコントロールされた電子書籍は、本を購入するのではなくて、閲覧権を購入するということ。
なもんで、ストア、サービスが終了したら購入した本は読めなくなる。
「本を買った」と思ってると、買った本が読めなくなるなんて論外で、確かに電子書籍は信用できない。その通り。
https://twitter.com/tanji_y/status/645384767525879808
とらのあなダウンロードストアも終了、閲覧認証の必要な購入物は再生不可に。それについて。
http://d.hatena.ne.jp/geromi/20150919/1442671230
またサービス終了によって、購入物の閲覧が不可になる現象が発生か。
電子はこういう現象があちこちで起きてるので買ってなかったから良かったものの
改めて電子書籍の信用の出来なさぶりがわかる。
今までどれだけサービスが終了となって「買った本」が読めなくなったというのがまとめられていて興味深いエントリだ。
わたしの場合、それほど所有欲がないし、何度も再読する本は限られた一部なので、サービスが終了して本が読めなくなってもそれほどダメージはない。もちろん「えええええ。そりゃないよ」とか言っちゃうとは思うけど、たぶん言うだけ。
再読したい本・手元に置きたい本は、別のストアでまた買うか、紙本で買うかな。
そもそものところ。ほんと、そんなにみんな、買った本を再読してるのかな。
また、紙本との比較で
https://twitter.com/KenAkamatsu/status/645428266833068032
というのも首肯できるところなんだけど、これはこれである意味、八百屋でさんまを買えないのはおかしい、というようなことだとも思う。
そこはこだわりもなく、割とどうでもいい話だと思う。というかちょっと違う話だ。
てのが、わたしの読者側からの視点。
ただ、本(電子書籍)を出している立場でいうと、読者が困るのは論外。
てめえの都合で勝手にサービスを終了して、それで読者が読めなくなるのはおかしいという声を上げてんだから、なんとかしろよ、と思う。売る側的に、機会損失というか信用失墜というか、企業責任というか、投げっぱなしジャーマンかよ、とか。
対策を考えなきゃいけない。
サービスが終了しても、うちには本(電子書籍のEPUBファイル)がある。本がなくなることはない。デジタルデータは劣化することなく手元にある。
再読したいと思ってもらえるようなコンテンツを提供できているとして、サービス終了で読めなくなった場合に、EPUBファイルを提供するというのが解決策だろう。今後は万が一ストアが終了、サービスが終了したような場合のために、奥付あたりに「こちらに連絡をいただければEPUBファイルを提供いたします」とURLとともに付記追記しておこう。
この「電子書籍は信用できない」という風物詩について。
電子書籍側属性のひとと一般との乖離は、たぶん相変らず埋まってなくて。
https://twitter.com/denshochan/status/645431421583015936
https://twitter.com/sleeping_husky/status/645445117952692224
犬子さん(@sleeping_husky)と電書ちゃん(@denshochan)のツイートが象徴的だと思う(わたしは犬子さんのツイートにまったくの同意)

さいたま新副都心、けやき広場のビール祭りはまったりしていて好きなイベント。
今日もたっぷり堪能いたしました。うーん、まんだむ。
ImageMagickを使わずperlだけで画像サイズを取得

ハイブリッド型EPUB3を生成するスクリプトのフィックスページ部分で画像サイズを取得する必要があった。
「かんたんEPUB3作成ハイブリッド型EPUB3対応版」http://t2aki.doncha.net/easy_epub-hybrid
定番のImageMagickを使えば簡単なんだけど、ImageMagickが簡単じゃなかった。
WINDOWSではImageMagickのインストールが必要で、さらにActivePerlをインストールしたら一緒にインストールされるppmを使ってImageMagickを使うためのperlのモジュールのインストールが必要。ユーザーさんに別途インストールしてもらうにはちょっとハードルが高い。
macはさらに致命的で、macport でインストールしても、パッケージがあったのでそれをインストールしても、ソースからコンパイルしても、肝腎のJPEG、PNGに対応したものを作れなかった(JPEGはどうにかこうにか、まずJPEGのライブラリをインストールしてmakeしなおしたらjpeg対応版ができたけど、PNGがお手上げ)
JPEGにもPNGにも対応したImageMagickを使ってるひとがいるようなので、わたしのスキル、知識不足。だけど、自分でうまく行ってないものをユーザーさんにインストールしてね、というのは無理すぎる。致命的。
「かんたん」を謳う以上、面倒くさいことはひとつでも増えちゃいけない。
てことで、扱うのはJPEGとPNGだけだし、perlだけで画像サイズを取得する方法を探してgoogleさま。
ありがたいことに、そのまま利用できるサブルーチンなどがいくつかアップされていた。
ただ、そのまま=ブラックボックスのまま使わせてもらうと、あとあとメンテの時などに困るのは火を見るより明らか。猿程度の理解は必要だろうと、画像について、その扱いについて調べたので、備忘録。
・PNGは簡単らしい。
| 16byte | 4byte | 4byte |
| width | height |
16byte目からの4byteに幅、続く4byteに高さのピクセル数が入っているので決め打ち。
seek(IMG, 16,0);
read(IMG, $buf, 8);
my($width, $height) = unpack("NN", $buf);
幅高さをネットワークバイトオーダーのビッグエンディアン(32bit)で取得するだけでOK。
・JPEGがちょっと面倒。
JPEGというのは複数のセグメントの塊
| マーカー | 2Bytes |
| セグメントサイズ | 2Bytes |
| セグメント本体 | 可変 |
画像情報を格納しているのはSOFという種類のセグメント。
マーカーというのは16進数の「FF」がセグメントの開始を表していて、これはどういうセグメントですよという内容を意味するのが「FF」に続く1Byteのバイナリ。
SOFセグメントのマーカーで、JPEGのベースラインは「FF」「C0」プログレッシブは「FF」「C2」ということらしい。
ファイルの先頭から見て「FF」が見つかったらそこからセグメントの開始となる(ファイル先頭と最後にはマーカーだけのセグメントがあるので、先頭の2Bytesは読み飛ばす)
必要なのはJPEGの情報が入ったSOFセグメント。
1)
4Bytes読み込む。
2)
unpackでマーカーとセグメントサイズを取得する。
3)
→マーカーの1byteがFFじゃなかったら終了。
→マーカーの1byteがFFでセグメント内容がC0かC2なら続くセグメント本体を読み込む。
→マーカーの1byteがFFでセグメント内容がC0でもC2でもなかったら、セグメントの本体サイズ分読み飛ばして次のマーカーからの4byteを読む
4)
画像サイズはセグメント本体先頭に入っている。
| サンプルの精度 | 画像縦サイズ | 画像横サイズ |
| 1Byte | 2Byte | 2Byte |
unpackで取得できる。
てことで、easy_epub-hybridに組みこんだサブルーチンが以下。
sub get_image_size{
my $self = shift;
my $args = shift;
open(IMG, $args->{image}) || return;
my $buf;
my $w; my $h;
binmode IMG;
if($args->{image} =~ m!¥.png!){
seek(IMG, 16, 0);
read(IMG, $buf, 8);
($w, $h) = unpack("NN", $buf);
}
else{
seek(IMG, 2, 0);
while(1){
read(IMG, $buf, 4);
my($mark, $c, $len) = unpack("H2 H2 n", $buf);
last if($mark ne ’ff’);
if($c eq ’c0’ || $c eq ’c2’){
read(IMG, $buf, 5);
($h, $w) = unpack("x nn", $buf);
last;
}
else{
seek(IMG, $len-2, 1);
}
}
}
close(IMG);
return {width=>$w, height=>$h};
}
スクリプトの中からImageMagickを使うシチュエーションのほとんどが画像サイズの取得なので、これは重宝しそうだ。
jpeg画像について、おそらく間違ってるところがあると思うので、きちんとした知識は以下のサイトへどうぞ。
参考にさせていただいたサイト
http://tohoho-web.com/lng/200003/00030402.htm
http://www2c.biglobe.ne.jp/~osakana/vc/pc/jpegsize.html
http://hp.vector.co.jp/authors/VA032610/JPEGFormat/marker/SOF.htm
http://www.setsuki.com/hsp/ext/segment/sof0.htm
情報、丁寧な解説ありがとうございます。
そういえば。Ingress Lv.15になった。なんかAP稼ぎだけで今イチ面白みがなくなってきたなぁ。


