Kindle Scribeで快適自炊PDF読書

# はじめに

自炊pdfをKindle Scribeで読むための便利な環境を作ります。

この記事にはコードの詳細はありませんが、コアとなるものは書いてありますので参考にして各自でやってみてくださいませ。別に難しい話ではありません、昨今ではChatGPTに手伝って貰えば誰でもプログラムを書けますね。いい時代になったものです。

この記事は、以下の記事から切り出して加筆したものを含みます。

[ScanSnapで一万冊の本をスキャンして管理して読むおはなし - Qiita](https://qiita.com/curtain6935/items/28908baa23cdc5667455)

# Kindle Scribe

E-Inkデバイスは各社から出ており、あえてAndroidではないDRM王国の製品を選ぶ必要もないといえばそうなのですが、

- 使用している300PPI 10インチパネルはamazonが一定期間の独占契約をしているとの噂[^1]で、しばらくは他社からこのE-Inkパネルを用いたものは出そうにない(他社の10インチものは224PPI)
- 他社のE-Ink端末に比べて数が出ているため、保護シートなどの入手がしやすい

[^1]:[Hands on Review of the Amazon Kindle Scribe - Good e-Reader](https://goodereader.com/blog/electronic-readers/hands-on-review-of-the-amazon-kindle-scribe)

という利点があります。

他方、WebDAVとネットワーク経由で同期するようなAndroidアプリをいれることはできませんので、DRM王国を必ず経由したWiFiか、USB接続で転送する必要があります。

# 私の読書の流れ

1. 人間: 書籍をスキャン
1. 機械: バッチ処理で最適化pdfを作成
1. 人間: web uiでタイトルを書き込み、縦書き二段組であればその旨を示すタグをつける
1. 機械: バッチ処理で縦書き二段組解除をしたpdfを作成
1. 人間: 読みたい本を、web uiからNextCloudに転送
1. 人間: macにKindleデバイスをUSB接続する
1. 機械: USB接続を検出してスクリプトにより転送・同期。このとき、Kinidleデバイス上にある読書進捗を示すファイルの中身をデコードし、読了していた場合（Kindle上で「既読」が表示されていた場合）は、読み終わったものとしてNextCloud上でpdfを「読了」に移動し、デバイスからはpdfを削除
1. 人間: Kindleデバイスで読書

# 最適化PDFの作成

ScanSnapなどのスキャナが生成したpdfから、以下の流れで最適化pdfを作成します。

1.  gsでPDFを300dpiのpngにする
2.  各ページについて、
    1.  ImageMagickで文字のある領域を判定する
    2.  文字の領域が狭ければ、そのページは白紙なのでスキップする
    3.  文字のある領域のみ取り出して、E-Ink端末にあった階調のpdfに変換する。
3.  全ページのpdfが揃ったらpdftkで繋げて一つのpdfにする
4.  pdftkでメタ情報を追加する

試行錯誤の結果、文字のある領域の判定には、

```sh:
convert ${入力画像} \
   -colorspace RGB -normalize \
   -level 0%,75%,0.6 -gamma 0.6 -ordered-dither threshold,16 \
   -virtual-pixel edge -blur 30 -fuzz 40% \
   -trim \
   -format '%wx%h%O' info:
```

とし、25x25以下を空白ページとしてスキップしています。

E-Ink向けのグレースケール化は、

```sh:
convert ${入力画像} \
    -crop ${上記のcrop範囲} \
    -colorspace gray -normalize \
    -level 0%,75%,0.6 -gamma 0.6 -ordered-dither threshold,16 \
    +repage \
    -bordercolor '#ffffff' -border 2%x2% \
    -define pdf:thumbnail=false -define pdf:interpolate=true \
    ${出力pdf}
```

としています。

# 縦書き2段組の分割

日本語の書籍では、縦書きの二段組になっていることがあります。そのままKindle Scribeで表示してもいいのですが、せっかくなので上下で分割して回転させることで、巨大な文字で目に優しい読書にします。

上記のステップ2.3の前に分割をいれます。

1.  ページ全体の、一行あたりの白いピクセルの数の平均をとる
2.  高さの0.3倍〜0.8倍の間に、平均より白い行が一定数以上連続する場所があるか調べる
3.  最も長く連続する場所で、その中間より少し下で分割
    -  段組の上の段の末尾は改行で揃わず白くなる傾向がある一方、下の段の行頭は揃っていて黒い傾向があるため、中間で分割すると上の段の行末が巻き込まれることがある
4. 分割後、再度cropして右に90度回転する

他にもアルゴリズムは考えられると思いますが、あまり凝っても遅くなるんですよね。

# KindleデバイスへのUSB転送

こちら参照

[ScanSnapで一万冊の本をスキャンして管理して読むおはなし#転送スクリプト - Qiita](https://qiita.com/curtain6935/items/28908baa23cdc5667455#%E8%BB%A2%E9%80%81%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88)

上記のスクリプトに、読書進捗状況に応じて読了pdfを削除する機能をつけます。

# Kindleデバイス上での読書進捗状況の取得

Kindle Scribeはpdfの読書進捗状況を、pdfのbasenameに`.sdr`をつけたディレクトリの中の拡張子`pdt`に書き込んでいるようです。

このファイルは以下のスレッドにあるpythonでデコードできます。多謝。

[KRDS - A parser for Kindle reader data store files - MobileRead Forums](https://www.mobileread.com/forums/showthread.php?t=322172)

`["lpr"]["position"]`の文字列の最初の値が読んでいる場所のページ数（マイナス1）のようですので、ここから最後のページまで読んだかどうかが取れます。

同様に、ブックマーク（クリッピング）の情報は拡張子`pds`に、`["annotation.cache.object"]["annotation.personal.bookmark"]`として入ります。
`My Clippings.txt`をパースするより簡単ですね。

# おわりに

以上でDRM王国の製品であるKindle Scribeを単なる便利な自炊PDFリーダーとして利用できるようになります。
WiFiオフにしておけば電池寿命も長くなりますよ。