テキスト中心の本のスキャンからjbig2で小さいPDFを作成する 2026年6月14日更新
スキャナーで作成したPDFや電子書籍のスクリーンショットで作成した画像からコマンドラインプログラムで小さいPDFを作成をする。ページ中のテキスト等はjbig2形式でモノクロに圧縮し、写真等はjpeg形式でPDFの元の位置にスタンプとして貼り付ける方針で。
PDFに透明テキストを埋め込む方法も書くがそれを作成するOCRは色々あるので NDLOCR-Lite を例として書く。
使用するソフトは jbig2enc (githubの本家のv.0.31は問題があるので左のリンクのv.0.29を使用)、ImageMagick、CPDF、BusyBox for Windows、Python 等。Pythonには pip install で opencv-python と img2pdf パッケージをインストールする。画像のPDF化は img2pdf.py の替わりに CPDF でもできるが作成されるPDFが常に72dpiになってしまうので使えない。
スクリーンショットの自動化方法については書かないので必要であれば何らかの方法でご自分でご用意下さい。
(1) スキャンでPDFが作成されるのであればその中からまず個々の画像ファイルを抽出する。Poppler の pdfimages.exe コマンドを使ったり、私のスキャナーのPDFは 画像梱包 でも抽出できた。
(2) 希望により何らかのツールで画像のサイズ(ピクセル数)を小さくする。変換後の画像形式は png がよい。サイズを小さくすれば作成されるPDFは小さくなるが、透明テキストを付けるのであれば、サイズを小さくし過ぎるとOCRの認識精度は下がってしまう。
(3) 作業フォルダーを作成して中に"pages"というフォルダーを作成してその中にページ順にソートできるファイル名で画像ファイルを入れる。コマンドプロンプトの dir コマンドのソート順が使われる。たとえば"8.png"、"9.png"、"10.png"というファイルがある時Windowsのエクスプローラーはその順でソートするが、dir では"10.png"→"8.png"→"9.png"となることに注意。"08.png"、"09.png"、"10.png"であれば問題ない。ツールで抽出した画像ファイルにはたいてい適切に連番が付いているのではないかと思う。
(4) (3) の作業フォルダーをカレントフォルダーにして
make_pdf.sh とget_img_pos.py
(後者の作成は簡単ではなかったので Gemini に作ってもらった)を置き、make_pdf.sh
中の *.exe にパスが通っていなければテキストエディターでフルパスを書き足し、*.py
のパスと最初の方にある dpi 変数の値を書き換える。
sh中のパスの区切り文字は"¥"ではなく"/"を使う(shではカレントフォルダーにパスは通っていないのでその場合には
./*.exe とする)。
また、magick.exe の引数を変更して写真等を好みの画質にする。
"-colorspace gray" を削除すればグレイスケールではなくなるし
"-quality 85" の数値はjpegの品質。
[パス¥]busybox bash -c ./make_pdf.sh
を実行すると"output.pdf" が作成される。
(5) 透明テキストを付けるのであれば、NDLOCR-Lite で"pages"フォルダーを処理対象フォルダーとして、 make_pdf.sh に書いたdpiを入力して出力ファイルを1つにまとめてPDFを作成する。その後 「OCRで作成されたPDFから「透明テキストを抽出・可視化」 を使って透明テキストPDFを作成する。
(6) 透明テキストを作成した場合 次のコマンドで"output.pdf"と結合できる。
[パス¥]cpdf -combine-pages output.pdf 透明テキスト.pdf -o
output2.pdf
(7) その後
[パス¥]cpdf -squeeze output2.pdf -o output3.pdf
を使うとファイルサイズが更に小さくなるかもしれない。
※ dpiは何を指定しても画面上で見た時の画質は変わらない。ただしPDFリーダーでプロパティーとして表示される縦横の寸法や100%表示にした時の大きさが違ってくる。スキャナーが作成するPDFのプロパティーの寸法はスキャンした紙の寸法となる。スキャナーのPDFはページごとに画像形式とdpiが異なることがある。
[パス¥]pdfimages -list PDFファイル
を実行するとdpiは x-ppi、y-ppi として表示される。
正しくPDFを変換するためにはそれに合わせてページ別にdpiを設定してPDFを変換してから結合すべきだが、上記スクリプトは
そのような作り込みをしていない。
なお、Windows画面のスクリーンショットはディスプレイのサイズに関係なく96dpiということになっている。