夜田たんの知的生活実践

ほそく・ながく・ゆるく続くブログを目指します(だいたい週一で更新中)

蔵書の電子書籍化(自炊)軽量化編

computer code on screen

Photo by Chris Ried  on Unsplash

前回の課題から、今回はファイルサイズの軽量化に取り組みます。
結果、解像度が同じだとあまり変わりませんでした!

今度の手順は

  1. PDFではなく画像としてスキャン
  2. 見開きを分割
  3. 画像を圧縮
  4. OCRしてPDFで出力

でやってみます。

使用した本

講談社学術文庫「本を読む本」
とりあえずテスト用として、見開き10ページ分をスキャンしました。

前回と同じ方法

スキャナの設定で、OCR済みのPDFファイルを直接作ります。
見開きを左右に分割して結合すると、結果は3.81MB。

新しい方法

まずは画像としてスキャン

変えたのは拡張子だけで、他はまったく一緒の設定です。

見開き画像を分割・PNGで保存

こちらはやっぱりPythonでざっくり作りました。

2020.06.22 ソースコード修正

以前のブログからのデータ移行時に、ソースコード内のディレクトリ区切り\\がごっそり抜け落ちていたので修正しました。申し訳ありません。

# --------------
FILE_PATH = 'C:\\Users\\hogehoge\\Desktop\\9784860641344'
PNG_FOLDER = 'png'
ROTATE_FOLDER = 'r'
# --------------

import os
import shutil
from PIL import Image
from PIL.ExifTags import TAGS

def rotate(img, basename):
    try:
        exif = img._getexif()
    except AttributeError as e:
        print(e)
        # 途中で止まったので普通のファイルコピーにする
        # img.save('.\\' + ROTATE_FOLDER + '\\' + basename)
        shutil.copyfile(basename, str('.\\' + ROTATE_FOLDER + '\\' + basename))
        return

    if exif != None:
        for key in exif.keys():
            tag = TAGS.get(key, key)
            if tag == 'Orientation':
                value = exif[key]
                print(value)
                break
        # print(Image.ROTATE_90) #2
        # print(Image.ROTATE_180) #3
        # print(Image.ROTATE_270) #4
        if value == 8:
            img = img.transpose(Image.ROTATE_90)
        elif value == 3:
            img = img.transpose(Image.ROTATE_180)
        elif value == 6:
            img = img.transpose(Image.ROTATE_270)
    img.save('.\\' + ROTATE_FOLDER + '\\' + basename)

# 作業用フォルダに移動
os.chdir(FILE_PATH)
# フォルダ作る
if not os.path.exists(FILE_PATH + '\\' + PNG_FOLDER):
    os.mkdir(PNG_FOLDER)
if not os.path.exists(FILE_PATH + '\\' + ROTATE_FOLDER):
    os.mkdir(ROTATE_FOLDER)


# 画像を全部見つける
files = os.listdir()
for file in files:
    if os.path.isfile(file):
        filename, ext = os.path.splitext(file)
        mihiraki = Image.open(file)
        # exif情報を見て画像を回転
        rotate(mihiraki, os.path.basename(file))
        mihiraki_ro_path = '.\\' + ROTATE_FOLDER + '\\' + os.path.basename(file)
        mihiraki_ro = Image.open(mihiraki_ro_path)
        mihiraki_R = Image.open(mihiraki_ro_path)
        mihiraki_L = Image.open(mihiraki_ro_path)
        width, height = mihiraki_ro.size
        mihiraki_R = mihiraki_R.crop((int(width * 0.5), 0, width, height))
        mihiraki_L = mihiraki_L.crop((0, 0, int(width * 0.5), height))
        # 左綴じ
        # mihiraki_R.save('.\\' + PNG_FOLDER + '\\' + filename + '_02R.png')
        # mihiraki_L.save('.\\' + PNG_FOLDER + '\\' + filename + '_01L.png')
        # 右綴じ
        mihiraki_R.save('.\\' + PNG_FOLDER + '\\' + filename + '_01R.png')
        mihiraki_L.save('.\\' + PNG_FOLDER + '\\' + filename + '_02L.png')

予想以上に手間取ったのが、JPEGはWindowsのエクスプローラ上で画像を回転させても、Exif情報を変えているだけで実データは回転してないということ。
自分の環境では、Exif情報を持てるはずのTIFFは、同様の操作をしても、直接画像ファイルを回転させているようで、Exifを編集しているわけではない様子。
このあたり勉強不足なのでイマイチ突っ込みきれていません。

圧縮

pngquantを使って、8色まで落とします。
pngquantはコマンドラインでもできるしPythonのラッパーもあるのですが、GUIの「PNGoo」の方がプレビューできて、出力先も指定できるので楽でした。
Pythonのラッパーは色数の指定ができなさそうだったので断念。

OCR+PDF出力

 $ dir /b > input.txt
 $ tesseract input.txt output_2 -l jpn_vert+jpn --dpi 300 pdf

tesseract-OCRを使って、コマンドプロンプト上で一気に仕上げます。
パスを通す時につまずいている人があまりいないようなのでメモを残しておきますが、自分の場合は、tesseractの実行ファイルへのパスとTESSDATA_PREFIXともに「ユーザー環境変数」ではなくて「システム環境変数」側のパスに追加しないと通りませんでした。
input.txtはPNGファイルの一覧なので、コマンドプロンプトの「dir /b」ですぐに作れます。

ファイルサイズ比較

3.56MB…ほぼ変わりません。
今回、スキャナ側で解像度を低く設定すると「OCRするからもっと解像度上げて!」とエラーが表示されてしまったので300dpiでスキャンしましたが、OCRはtesseract側でやると決めれば、スキャン時に解像度を低く抑えて、もっとサイズダウンできそうです。

追加

後からPNGを200dpiに落として、サイズも70%にしてから、PNGooで減色した上でtesseractに通してみました。
この結果、1.85MB。見開き10ページ分としてはこれくらいまで抑えたいですね。

今後の課題

[済]PDFをサイズダウンする方法を探す

これは今回でほぼ解消とします。

とにかく素早くスキャンして、後から一括で補正する方法を探す

次回以降へ持ち越しです。

[済]綴じ方向を修正

PDF_R2Lという超ありがたいフリーソフトが見つかりましたので当面使わせていただきます。
あとは、どうやらAcrobat(有料)だと可能な様子。
綴じ方向もPDFファイルの一情報なので、さくっとPythonでできそうな気がするのですが、先達が意外と情報が見つかりません。

参考資料

今回も色んなサイトに大変お世話になりました。

  • Like!