本記事の目的は、Macで複数ページのpdfを一気にjpegに吐き出す操作を、端末から行うことです。有名な方法としては、Automatorを用いたものがありますが、自動化には不適なので、ここでは端末を使います。というかAutomatorよくわからん…。
MacにおけるPDF→JPEG変換
OSXでpdfファイルをjpeg画像に変換しようと思ったら、標準のプレビューアプリを使うのが一番てっとりばやいです。しかしこれだと、1ページずつしか出力できず、とてもやっていられません。そこで複数ページを一括で変換する際は、Automatorを使用するやり方が有名なようです。ようです、というのは私はこのAutomatorの使い勝手がイマイチよくわからず、あまり使ったことがないからです。
せっかくのUNIXですから、自動化にうってつけなのはやはりコマンドラインだと思います。ということで、Macの端末上からpdfをjpegに変換する手順を書きます。おまけで、jpegをzipに圧縮します。さらにおまけで、一連の処理を自動化したRubyスクリプトも最後に付記します。
使用するソフトウェア
使用するソフトウェアはImageMagickとPoppler。ImageMagickのcovertコマンドだけでもjpegにはできるのですが、なんだか画質が荒い。同様に、Popplerのpdftoppmコマンドにも、toppmといいながら-jpegオプションがあるのですが、これもちょっと荒い。調整することもできるのかもしれませんが、ヘルプを見てもちょっとわからず。結局、pdftoppmで一度ppmにした後、convertでjpegにするのが簡単でかつ綺麗でした(下図)。
Homebrewがあることを前提に、以下のコマンドでインストールします。Homebrewがない場合はまずそのインストールから(「Homebrew — OS X 用パッケージマネージャー」より、コピペ一発でインストール可)。
$ brew install imagemagick
$ brew install poppler
参考:表示範囲 (CropBox) を考慮して PDF のサムネイルをつくる - Qiita
コマンドの実行
input.pdf を、output-NUMBER.jpg のように出力する場合、以下のように実行します。
$ pdftoppm input.pdf buf
-> buf-1.ppm, buf-2.ppm ... と出力される
$ convert *.ppm output.jpg
-> output-0.jpg, output-1.jpg ... と出力される
$ rm -f *.ppm
-> いらないppmはお掃除
さらに、以下でoutput.zipにします。
$ zip -r -m output.zip output*.jpg
jpgファイルが残るのが鬱陶しい場合は、-jオプションを付記すると、zip圧縮後、jpg画像が残りません。その他の注意点としては、ファイル名に空白が挟まると、ワイルドカードからの展開の仕方によってエラーが起きる可能性があります(通常は空白が区切りなので)。空白が含まれるファイルは多いので、なにかしらの対応が必要があるかもしれません(参考:「逆引きシェルスクリプト/スペースが含まれる文字列を1行として扱う方法 - Linuxと過ごす」)。
おまけ:一連の処理をまとめたRubyスクリプト
私はちょいちょいpdfを画像化することがあるので、一連の処理を簡単なRubyスクリプトにしています。そのスクリプトをおまけでつけておきます。OSXって最初からRuby入ってたかどうか覚えていませんが、Rubyが使えるなら以下のスクリプトをコピペして、pdfファイルを引数に渡して実行すると、pdfをjpgで固めたzipに変換します。以下スクリプト名をpdf2zip.rbとしたときの使用例。
$ ruby pdf2zip.rb test/*.pdf
-> testディレクトリ以下に出力されます。
以下ソースコード。
#!/usr/bin/env ruby
# coding: utf-8
require 'fileutils'
class Pdf2Zip
def initialize(file)
@target_path = file
@name = File.basename(file, ".pdf")
@dir = File.dirname(file)
end
def to_zip
files = _pdf2jpg()
zip_file = _jpg2zip(files)
end
def _pdf2jpg
buf = "#{@dir}/#{@name}"
norm_ppm = Dir.glob("#{Regexp.escape(buf)}*.ppm")
system('pdftoppm',@target_path,buf)
ppm_list = Dir.glob("#{Regexp.escape(buf)}*.ppm")
ppm_list = ppm_list - norm_ppm
files = Array.new
ppm_list.each{|f|
next if File.extname(f) != '.ppm'
jpg_name = f.sub(".ppm",".jpg")
system('convert',f,jpg_name)
files.push(jpg_name)
}
FileUtils.rm(ppm_list)
return files
end
def _jpg2zip(files)
zip_file = "#{@dir}/#{@name}.zip"
zip_ary = ['zip','-r','-m',zip_file] + files
system(*zip_ary)
return zip_file
end
def to_s
p @target_path,@dir
end
end
# subroutine
def pdf2zip(file)
pdf_file = Pdf2Zip.new(file)
puts file
pdf_file.to_zip
end
def usage
puts "Usage: $ ruby #{File.basename($0)} [FILES]"
exit
end
# main
usage if ARGV.size == 0
usage if (ARGV[0] == '-h') or (ARGV[0] == '--help')
flist = ARGV.dup if ARGV.size > 0
flist.each{|f| pdf2zip(f) if '.pdf' == File.extname(f)}
ちなみに、私はzipをそのままcbzに変更することが多々有ります。その場合to_zip関数の最後の行に「FileUtils.mv(zip_file, zip_file.sub('.zip','cbz'))」を付記するなどで良いでしょう。
コメント