自炊ファイルをRubyでPDFに変換


タブレットやKindleなどの普及で自炊が身近になりました。
今回はRubyを使って自炊した画像をPDFに変換するプログラムを作ってみました。
プログラムは自由に改変して使用していいです。


ImageMagickで簡単にPDF化(準備)

Rubyプログラムを作成するのは慣れていないのですが、簡単なものでjpgやPNGデータをPDFに変換することができます。

PDFの作成にはImageMagickを使用します。私の環境はMacなのでHomebrewを使用してインストールをしてみます。

$  brew install imagemagick

上記のコマンドでImageMagickインストールします。
次に、zipやrarなどの圧縮ファイルなどがある場合のための準備をします。

$  brew install unrar

zip用の解凍コマンドはあるので、rar用のコマンドをインストールします。
今回のファイルではRubyのライブラリ「fileutils」を使用するので、gemにてインストールをしておきます。インストール方法は調べたらでてくると思います。

ImageMagickで簡単にPDF化(プログラム編)

さて、次にプログラムです。色々不具合があるかもですので、自己責任でお願いします。

#!/usr/bin/ruby
# -*- coding: utf-8 -*-

require 'fileutils'

# ================================================
# 設定
# ================================================
$Dir_Path = "変換元のディレクトリ フルパス"        # 変換元のディレクトリ
$PDFPATH = "PDFを格納するディレクト フルパス"      # 変換後のPDFを格納するディレクト

$CONVERT_DIR = "#{$Dir_Path}convert"            # コンバート完了ディレクトリ
$ERROR_DIR = "#{$Dir_Path}error"                # コンバート失敗ディレクトリ
$TEMP_DIR = "#{$Dir_Path}tmp"                   # ログ用テキスト
$LOG_TXT = "#{$Dir_Path}log.txt"                # ログ用テキスト

$setImgPath = []
$img_jpg = "**/*"                            # ディレクトリを再帰的に検索

FileUtils.mkdir_p($PDFPATH) unless FileTest.exist?($PDFPATH)
FileUtils.mkdir_p($CONVERT_DIR) unless FileTest.exist?($CONVERT_DIR)
FileUtils.mkdir_p($ERROR_DIR) unless FileTest.exist?($ERROR_DIR)
FileUtils.mkdir_p($TEMP_DIR) unless FileTest.exist?($TEMP_DIR)

# ================================================
# ディレクトリ削除
# ================================================
def deleteall(delthem)
  if FileTest.directory?(delthem) then  # ディレクトリかどうかを判別
    Dir.foreach( delthem ) do |file|    # 中身を一覧
      next if /^\.+$/ =~ file           # 上位ディレクトリと自身を対象から外す
      deleteall( delthem.sub(/\/+$/,"") + "/" + file )
    end
    Dir.rmdir(delthem) rescue ""        # 中身が空になったディレクトリを削除
  else
    File.delete(delthem)                # ディレクトリでなければ削除
  end
end
# ================================================
# PDF作成
# ================================================
def makePDF(path)
  pathName = File.basename(path).gsub(/\(|\)|\s|\[|\]|;/,"_")              # フォルダ名の取得
  pathName = pathName.gsub(/__/,'_').gsub(/^_/,'')
  $PDFName = "#{$PDFPATH}/#{pathName}.pdf"    # PDFのファイル名はフォルダ名を使用
  puts "#{pathName} を変換"
  Dir.chdir(path)   # ディレクトリの変更
  #{}`ls -al`
  countFile = Dir.glob("*.jpg").count + Dir.glob("*.png").count + Dir.glob("*.JPG").count + Dir.glob("*.PNG").count

  # ================================================
  # 画像ファイルがない場合は小階層まで確認
  # ================================================
  if countFile == 0
    countFile = Dir.glob("./**/*.jpg").count + Dir.glob("./**/*.png").count + Dir.glob("./**/*.JPG").count + Dir.glob("./**/*.PNG").count
    # 小階層にも画像がない場合は無視
    if countFile == 0
      File.open($LOG_TXT,"a") { |file|
         file.puts "#{pathName} ... 無視"
      }
      FileUtils.mv(path, $ERROR_DIR)
      return false
    end
  end

  $setImgPath.clear()   # 配列をクリア

  # ================================================
  # 画像ファイル名を配列に格納
  # ================================================
  Dir.glob($img_jpg) do |img|
    next unless img.index(/.jpg|.png|.JPG|.PNG/)
    $setImgPath.push("\"#{img}\"")
  end
  setImg = $setImgPath.join(" ")    # 書き出し用に配列の文字を連結

  # ================================================
  # シェルスクリプトにてImageMagicを使用
  # ================================================
  `convert #{setImg} #{$PDFName}`

  # ログ出力
  File.open($LOG_TXT,"a"){|file|
    file.puts "#{pathName} をPDF化 ... 成功"
  }
  depthPath = File.expand_path(path)
  if depthPath.index(/\/tmp/)
    deleteall(depthPath)
  else
    FileUtils.mv(depthPath, $CONVERT_DIR)    # 処理済みのファイルを移動
  end
end

# ================================================
# Zip RAR解凍
# ================================================
def unzip(d)
  fileName = File.basename(d).gsub(/\.zip|\.rar/,'')
  FileUtils.mkdir_p("#{$TEMP_DIR}/#{fileName}") unless FileTest.exist?("#{$TEMP_DIR}/#{fileName}")
  FileUtils.mv(d, "#{$TEMP_DIR}")
  zipdir = "#{$TEMP_DIR}"
  Dir.chdir("#{zipdir}/#{fileName}")
  zipdirName = "#{$TEMP_DIR}/#{File.basename(d)}"
  if d.index(/\.zip/)
    `unzip "#{zipdirName}"`
  else
    `unrar x -y "#{zipdirName}"`
  end
  FileUtils.mv(zipdirName, $CONVERT_DIR)
  return d = Dir.glob("#{$TEMP_DIR}/*")[0]
end

# ================================================
# 実行
# ================================================
dirs = Dir.glob("#{$Dir_Path}**") # 指定したディレクトリの取得
dirs.each do |d|
  next if d.index(/\/convert|\/error|\/tmp/)  # convertとerrorディレクトリは無視
  if d.index(/\.zip/) || d.index(/\.rar/)
    d = unzip(d)
    depthArchive = Dir.glob("#{d}/**")
    depthArchive.each do |dep|
      if dep.index(/\.zip/) || dep.index(/\.rar/)
        if dep.index(/\.zip/)
          `unzip "#{dep}"`
        else
          `unrar x -y "#{dep}"`
        end
      end
    end
  end
  next unless FileTest.directory?(d)
  #puts d
  makePDF(d)
end

というプログラムになります。

流れとしては、

  1. 指定されたディレクトリからフォルダと圧縮ファイルを検索し、圧縮ファイルの場合はtmpフォルダに解凍します。
  2. そして、makePDFにてフォルダ名をファイル名としてPDFファイルを作成。
  3. 終了したものはconvertフォルダへ、変換できないものはerrorフォルダへ格納
  4. tmpフォルダに展開したファイルは削除

以上のようになります。

あとはrubyを実行することで、対象のフォルダからフォルダや圧縮ファイルを検索し、PDFを作成していきます。
cronに登録することもありです。

色々と問題がありますが、自分にとってはこれで十分です。
使用する際は自己責任でお願いします。エラー処理とか一切していないので、不具合が多いです…

まだまだRubyに触って日が浅いのですが、簡単に自炊したファイルをPDFに変換することが出来ました。

Next Post次の投稿 Previous Post前の投稿 ホーム