Featured image of post Macで複数ページのpdfを一括でjpegにコマンドラインで変換する

Macで複数ページのpdfを一括でjpegにコマンドラインで変換する

本記事の目的は、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にするのが簡単でかつ綺麗でした(下図)。

[caption id="" align=“alignnone” width=“480”]スライド3 pdftoppm -jpeg と pdftoppm -> convert の比較[/caption]

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’))」を付記するなどで良いでしょう。

コメント

コメントは承認後に表示されます。

まだコメントはありません。

コメントを書く

或る阿呆の記.
Hugo で構築されています。
テーマ Stack は Jimmy によって設計されています。