「ImageMagickを使ってPDFを画像に変換したい。許可を」「よし、やっちまえ」

この記事はだいぶ前に書かれたものなので情報が古いかもしれません
記事のタイトルを映像化するとこうなる

この記事を三行にまとめると

PDFを画像にしたいことってあるよねー
ふいー、長い戦いでしたねー
僕ももっとなめらかに動くGIFアニメーションが作れるようになりてーよ
PDFを画像にしたいことってあるよねー。

それを可能にするのがImageMagickというやつなんですが、これを使えばできるよと言うのは簡単だけど、いざ使えるようにするまでがなかなか面倒。俺は長門さんのような宇宙的パワーを持っていないから、ちょちょちょっとサーバーのセッティングをしてはいオーケーってわけにはいかないのです。むしろ長門さんクラスのお方なら、もっとセッティングが簡単で使いやすい自前のライブラリを作ってしまいそうだね。

まあとにかく。

今回は結構手間がかかった上に、分かんないことが多すぎて、要所要所でエラーが出て先に進まなかったので、似たような目に遭う人を一人でも減らすべく、今ここでその全貌を明らかにしておきましょう。

正しい道順だけじゃなくてエラーが出たところも書いていくから、かなーり長くなると思うんで、ダッシュで説明していきますよ。

ふふふ、果たして俺のスピードについてこられるかな?



おっと、そうだ。念のため。

サーバーはCentOS6.0っていう前提で話します。場合によってはここに書いてあるのと違うパッケージとか入れなきゃいけないことがあるかもだから、注意です。



Ghostscriptを先に入れとこう

ImageMagickを使うには、Ghostscriptっていうパッケージが必要になる。なので、まずはそれをサーバーに入れましょう。

今回はやむらない。「やむる」っていうのは、あかつきのお宿ではお馴染みの単語なんだけど、「yum」コマンドを使うって意味ね。この言葉、何とかしてエンジニア業界に浸透させられねーかなぁ。

ここでは「make」コマンドを使ってコンパイルします。

まずは必要なファイルを落としてきて解凍する。こんな風に。

# wget http://ftp.jaist.ac.jp/pub/sourceforge/g/gh/ghostscript/GPL%20Ghostscript/9.07/ghostscript-9.07.tar.gz
# tar xzvf ghostscript-9.07.tar.gz

解凍する場所はどこでも良いと思うけど、いっぱいファイルがあるし、コンパイルしたらもっとファイルがいっぱいになるから、適当にghostscriptっていうフォルダとか作ってやるのが良いと思う。

解凍できたら、makeコマンドを使ってコンパイルしましょう。

# ./configure --disable-compile-inits --with-x --with-drivers=ALL --without-luratech --with-libiconv=gnu --prefix=/usr/local
# make
# make install

「./configure」っていうのは、makeをする前に必要になるやつなんだけど……その後ろにくっついてる「–disable〜」とかは、正直何を意味しているのかはよう分かりません。すまんす。ググってくだされ。

とりあえず僕が調べた限りでは、Ghostscriptをコンパイルするときにはこういう風に書いてやるらしい。

特にエラーが出てコンパイルが止まったりしなければ、無事にGhostscriptが使用可能な状態になってると思います。



コンパイルできない場合

上記のやり方でコンパイルできれば何の問題もないんだけど、例えばこんなエラーが出たりすることがある。

//コマンド実行
# ./configure --disable-compile-inits --with-x --with-drivers=ALL --without-luratech --with-libiconv=gnu --prefix=/usr/local

//エラー内容
no acceptable C compiler found in $PATH

「コンパイラがないよ〜」みたいなエラーですかね。

そんなときは、まずコンパイラをインストールする。これはやむって入れられるから簡単よ。

# yum -y install gcc

それから、makeコマンドを実行しようとしたときに「makeコマンドなんて知らねーよ」ってサーバーに怒られることがあるかもしれない。そんときゃ、makeもやむって下さい。

# yum -y install make



ImageMagickを入れるわよ

じゃあいよいよImageMagickを投入するぜ。ここまでのは、鍋で言えば野菜を入れただけの状態だ。こっからお肉を入れていくよ。

まあ、ImageMagickもGghostscriptとやり方は一緒です。ファイルを落っことしてきてコンパイルする。

# wget ftp://ftp.kddlabs.co.jp/graphics/ImageMagick/ImageMagick.tar.gz
# tar zxvf ImageMagick
# ./configure
# make
# make install

こんな感じかな。これもいっぱいファイルができるから、適当なフォルダを作ってからやった方が良いと思います。

これも無事にコンパイルできていれば、ひとまずサーバー上でImageMagickが使えるようになっているはず。試しにPDFを画像に変換して確かめてみよう。

# convert sample.pdf sample.png

変換するには「convert」というコマンドを使います。

これで、例えばsample.pdfが10ページのPDFファイルだったとしたら、同じ階層のところに「sample-0.png」「sample-1.png」と0から連番が振られた画像ファイルが作成されます。

もしできないようなら……うーん、僕はこれでできたから、もしできなかった場合にどんなエラーなのかっていうのが分からないんだけど……今SSHで接続しているユーザーが、そのファイルに対する権限を持ってないとか? それとも、今いるフォルダへの書き込み権限がないとか? そういうの関係あんのかな。



とまあ、こんな感じでImageMagickをサーバーに入れて、PDFを画像に変換させることができます。

「なかなか面倒って言ってたわりには、そこまででもなくね? 要所要所でエラー出たとか言ってたけど、ほとんど出てないじゃん」とか思った?

はっはっは、慌てるでない。面倒なのはこっからなんだよ。



PHPの中で変換処理をしたいなら

ターミナルとかTeraTermで接続したときにだけ変換できれば良いってんなら、ここまででオーケーなんですけど、ま、だいたいの場合、そこで終わりとはならないよねー。プログラムの中で使いたいっていう方が圧倒的に多いと思うの。

なので、PHPでImageMagickを使えるようにしましょう。



PHPで使えるようにするには、「imagick」っていうモジュールを使うことになる。なのでそれをインストールする。

imagickは、やむらずに「pecl」っていうコマンドを使って手に入れる。何でかってーと……何でかな? imagickっていうのがpeclのモジュールだから……って説明で良いのかしら?

まあいいや。とりあえずやっちゃおう。

# pecl install imagick

もしインストールが上手くいったのなら、次はiniファイルを作る。ちなみに僕は上手く行かなかった。それについては後述します。

たぶんだけど、「etc」っていうフォルダの下に「php.d」ってフォルダがあると思うんで、そこに「imagick.ini」っていうファイルを作りましょう。別にファイル名は何でも良いと思うけどね。拡張子がiniであれば。「super-ultra-megamax.ini」とかでもちゃんと動作すると思う。大事なのは中身だから。ファイル名がどんなにイタいものでも、誰も気にしないから大丈夫だよ。

一行だけ書きたいことがあるんで、viモードで編集します。

# vi /etc/php.d/imagick.ini

//imagick.iniの中に記述
extension=imagick.so

ここで一度、apacheを再起動します。そうしないと、imagick.iniが認識されない。

無事に再起動が終わったら、もう、言うことは何もない。それでPHPの処理の中でPDF→画像変換ができるようになっているはず。

さあ、今すぐやってみるんだ。キョンに許可を求める必要はない。



コマンドがないかもしれない

もし、こんなエラーが出てimagickのインストールができなかった場合。

phpize: command not found

「phpizeがないぜー。ないコマンドはいくら俺でも叩けないぜー」って言われてる。

どうやらサーバーにPHPをインストールするときに、「php-devel」ってのをインストールしていないと、このエラーが出ることがあるそうです。

なので、これが出たときにはこうだ。えいっ!(声:松岡修造)

# yum -y install php-devel

そしたらもう一度peclコマンドでimagickのインストールにチャレンジしてみよう。

もしインストールが上手くいったのなら、もう、言うことは何もない。それでPHPの処理の中でPDF→画像変換ができるようになっているはず。

さあ、今すぐやってみるんだ。キョンに許可を求める必要はない。そしてこんなことは二回言うほど大事なことでもない。

あ、もちろんiniファイルは忘れずに作るんだよ? これは大事なことだから。



他にも足りないものがあるかもしれない

もし、それでもダメだったら。

僕の場合はダメだったんだけど、今度はこんなエラーが出た。

You will need re2c 0.13.4 or later if you want to regenerate PHP parsers.

まあ何かよく分かんないけど、re2cとかいうのが足りないって言われてるみたい。

で、ですね。

たぶん、そのre2cっていうのをやむるか何かでインストールすれば問題は解決したのかもしれないんですが、僕の場合はこれで解決しました。

# yum -y install ImageMagick-devel

ImageMagick-develの中に、re2cがあったんですかね。僕が調べた参考文献の中では、こうやって解決してる人がいたんで、僕も真似させてもらいやした。

今度こそ、三度目の正直っつーことで、peclコマンドを叩こう。

もしインストールが上手くいったのなら、手を叩こう。ぱちぱちぱち。



実際どんな風に使うのか

先に一言だけ申し上げておきたいんですが、ここの項目だけは想像で書かれてます。

つまり、調べただけで実際に動作の検証はしていないということ。何でなのかは後で話します。

とりあえず、こう書けば変換ができるらしいってことを書いとくんで、参考の足しにしてください。

こちら(↓)のサイトに書いてある内容を参考にさせていただきました。あざっす。

毎度のことながら、僕がこう言う場合の参考は、丸パクリを意味します。パクってすみません。

PHPで簡単にPDFを全ページ画像に変換する方法|本を買わずに解決するWeb制作の小技

$im = new Imagick();
$im->readImage('sample.pdf');
$totalPage = $im->getImageScene();

for ($i = 0; $i <= $totalPage; $i++) {
  $im->setImageIndex($i);
  $im->thumbnailImage(640, 640, true);
  $im->sharpenImage(0, 1);
  $im->writeImage('sample_' . $i . '.png');
}

$im->destroy();

ページ数を取得して、一枚ずつ画像にしていく感じのようですね。



で、どうして僕がこれを想像だけで検証してないのかっていうと、どうしても解決できないエラーが出てしまって、結局変換できなかったんですよ。

二行目の「$im->readImage(‘sample.pdf’);」のところでFatalエラーが出てしまって、しかもそれが全く解決できないと来たもんだ。

何かね、こんな感じのエラー。

Fatal error: Uncaught exception ‘ImagickException’ with message ‘Postscript delegate failed・・・

いろいろ調べた結果、どうやら Ghostscriptの方に問題があるらしいってとこまでは分かったんですよ。バージョンが古いせいだとか、何かのパスが違ってるとか。

で、それらを端からやってみたんですけど、それでもエラーが消えない。いつまで経ってもイメージがリードできない。ウェーブにもライドできないし、解決できないフラストレーションもハイドできない。だからって、うっぷんを晴らすために、その辺を歩いている人をジェノサイドするわけにもいかないし。

まあそういうわけでして、いろいろやってはみたつもりなんですが、結局できなかったので、そのうち僕は考えるのを止めました。



でもいいんだ。サーバーでconvertコマンドを叩けば変換できるのは分かってんだから、このやり方がダメだったとしても、execとかsystemとかを使って、PHPからコマンド叩けば良いだけだもん。

と、思ってたんですけどぉ……。



PHPからコマンドを叩いた場合

ターミナル上で直接コマンドを叩く場合は普通に変換できるのに、PHPからコマンドを叩くと、なぜかエラーが出て上手くいかないのよ。

//PHPの処理
system('convert sample.pdf sample.php');

//実行結果
Error: /undefined in findresource Operand stack: --dict:8/17(L)-- TT2 1 --dict:5/5(L)-- --dict:5/5(L)-- MS-PGothic --dict:11/12(ro)(G)-- --nostringval-- CIDFontObject --dict:7/7(L)-- --dict:7/7(L)-- Adobe-Japan1 Execution stack: %interp_exit .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- --nostringval-- --nostringval-- false 1 %stopped_push 1862 1 3 %oparray_pop 1861 1 3 %oparray_pop 1845 1 3 %oparray_pop --nostringval-- --nostringval-- 2 1 2 --nostringval-- %for_pos_int_continue --nostringval-- --nostringval-- --nostringval-- --nostringval-- %array_continue --nostringval-- false 1 %stopped_push --nostringval-- %loop_continue --nostringval-- --nostringval-- --nostringval-- --nostringval-- --nostringval-- --nostringval-- %array_continue --nostringval-- --nostringval-- --nostringval-- --nostringval-- --nostringval-- %loop_continue Dictionary stack: --dict:1155/1684(ro)(G)-- --dict:1/20(G)-- --dict:75/200(L)-- --dict:75/200(L)-- --dict:106/127(ro)(G)-- --dict:285/300(ro)(G)-- --dict:22/25(L)-- --dict:4/6(L)-- --dict:26/40(L)-- Current allocation mode is local Last OS error: 2

エラー長くて見づらいけどごめんね。

とにかく、こういう結果が返って来ちゃって、PDFの変換ができない。

どうやらサーバーにインストールされてるフォントが問題らしくて、PDFの中で使われているフォントが足りてないとこうなるみたいです。

同じようなエラーに悩まされている人は他にもいたのですが、彼らはmsttcorefontsっていうパッケージをインストールして解決したみたいです。なので、僕もやってみました。

msttcorefontsってのは「Microsoft’s TrueType core fonts」の略だから、マイクロソフトの代表的なフォントなんですかね。



まずは準備から

msttcorefontsをインストールするためには、次の三つのパッケージを用意しなければならない。

・rpm-build
・ttmkfdir
・cabextract

上の二つはやむればいいんだけど、cabextractだけはrpmコマンドを使ってインストールします。

//rpm-build、ttmkfdirのインストール
# yum -y install rpm-build ttmkfdir

//cabextractのインストール
# wget http://www.cabextract.org.uk/cabextract-1.4-1.i386.rpm
# rpm -ivh cabextract-1.4-1.i386.rpm 

特別難しいことはないんだけど、もしかしたらcabextractだけはすんなりインストールできないかもしれない。僕の場合はそうだった。



32bitと64bitのお話

僕の場合、上記のやり方でrpmコマンドを叩いたら、以下のようなエラーが出た。

libc.so.6 は cabextract-1.4-1.i386 に必要とされています

ただ、findコマンドを使って検索してみると、ちゃんとサーバーの中には入ってたんですよ。

# find / -name libc.so.6

//検索結果
/lib64/libc.so.6

じゃあ何でエラーが出たかって言うと、この「lib64」っていうフォルダは、CentOSの64bit用のライブラリとかが入っているフォルダなんですよ。

えーっと、僕もあんまり分かってないんで説明が分かりづらいかもですが、CentOSには32bitと64bitの二つがあって、それぞれの場合で、参照先が違ったりする。

rpmファイルなんかだと、ファイル名に「i386」とかが入ってるのは32bit用で、「x86_64」とかが入ってるのが64bit用らしい。ほら、上の「cabextract-1.4-1.i386.rpm」にもi386って入ってるじゃん?

ってことは、このrpmファイルは32bit用であり、その際に使用するlibc.so.6も32bit用の方ってことになるんですよ。だけどうちのサーバーには64bit用のしかない。

ってことで、32bit用のlibc.so.6を入れましょう。

libc.so.6を入れるには、glibcというパッケージをやむる。

# yum -y install glibc.i686

今回の場合、明示的にi686とつけることで、32bit用の方をインストールするようにしています。たぶん、何もつけないと勝手に64bitの方がインストールされちゃうんだと思う。

これでもう一度cabextract-1.4-1.i386.rpmを入れたところ、上手くいきました。



yumの変わった使い方

ちょっちこぼれ話を。

今、libc.so.6を入れるにはglibcをやむれば良いって言いました。まあ、こういうのは「32bit libc.so.6 インストール」とかでググれば分かることなんですが、yumコマンドを使って調べることもできる。

# yum whatprovides libc.so.6

//実行結果
 * base: ftp.iij.ad.jp
 * extras: ftp.iij.ad.jp
 * updates: ftp.iij.ad.jp
base                                                                                                  | 3.7 kB     00:00     
extras                                                                                                | 3.4 kB     00:00     
updates                                                                                               | 3.4 kB     00:00     
vmware-tools  
glibc-2.12-1.107.el6.i686 : The GNU libc libraries
Repo        : base
Matched from:
Other       : libc.so.6

glibc-2.12-1.107.el6_4.2.i686 : The GNU libc libraries
Repo        : updates
Matched from:
Other       : libc.so.6

glibc-2.12-1.107.el6_4.4.i686 : The GNU libc libraries
Repo        : updates
Matched from:
Other       : libc.so.6

glibc-2.12-1.107.el6_4.4.i686 : The GNU libc libraries
Repo        : installed
Matched from:
Other       : Provides-match: libc.so.6


僕も初めて知ったんですけど、yumにはwhatprovidesっていうオプションがあるみたいで、それを使うと上記のような結果が得られる。ほら「glibc-2.12-1.107.el6.i686」とか書いてあるじゃん?

ここから、glibcってのを入れれば良いのかーってのが分かるわけですね。

どんなときでも使えるってわけじゃないらしいんですが、ググる前にとりあえずやってみるってのも、有効かもしれないです。

じゃ、本題に戻りましょう。



msttcorefontsをインストール

無事に準備が整ったところで、次は先ほどインストールしたrpmbuildコマンドを使って、msttcorefontsをインストールしていきます。

# wget http://corefonts.sourceforge.net/msttcorefonts-2.5-1.spec
# rpmbuild -bb msttcorefonts-2.5-1.spec

-bbっていうのは、specファイルを使ってrpmファイルをビルドするときに使うオプションってことらしいんですが……確かに今回落としてきたファイルは拡張子がspecっすね。

まあ何にせよ、これでいくつかのTrueTypeのフォントがサーバーに入りました。

実際に「/usr/share/fonts」の下を見てみると、「msttcorefonts」っていうフォルダができていて、その中に拡張子がttfのファイルがいくつか入っているはずです。arial.ttfとか。それがフォントファイル。



Ghostscriptでフォントが認識されるようにする

残念ながらまだ終わりじゃないぞよ。インストールしただけではダメなのじゃ。

Ghostscriptをインストールしたことで、etcってフォルダの下にghostscriptっていうフォルダができているはず。さらにその中を見ていくと「cidfmap.local」というファイルがある。

階層としては「/etc/ghostscript/バージョン/cidfmap.local」かな。バージョンのところは、僕の場合は「8.70」ってなってた。

このファイルをviモードで編集する。例えば、さっきもちょっと出てきた「arial.ttf」っていうフォントファイルを使う場合。

# vi /etc/ghostscript/8.70/cidfmap.local

//以下を記述
/Arial << /FileType /TrueType /Path (/usr/share/fonts/msttcorefonts/arial.ttf) /SubfontID 0 /CSI [(Artifex) (Unicode) 0] >> ;

SubfontIDとかCSIとかは何のことやらって感じだけど……Pathのところは、arial.ttfファイルが置いてあるパスを入れれば良いみたいですね。

これで「Arial」っていうフォントがghostscriptで使えるようになる。つまり、ImageMagickを使うとき、PDFファイルの中にArialというフォントを使った文字が書かれていてもエラーは出ない! ふはは、完璧!



でも俺の場合は……

ま、ここまで結構な長さを使っておいてあれなんですが……これは、Arialっていうフォントが使われていた場合の話で、僕の場合はまたちょっと違った。

さっきの、PHPからconvertコマンドを叩いたときに出たっていうあの長ったらしいエラーの中を見ると、「MS-PGothic」って文字があるんですよ。つまり僕の場合は、PDFファイルの中にMSPゴシックを使った文字が出てきてて、それが上手く変換できないからエラーになってたんですね。

MSゴシックっつったらマイクロソフトの代表的なフォントの一つのような気もするんですが、でもここまでの手順を踏んでも、MSゴシックのフォントファイルは「/usr/share/fonts」の下にない。

ってことで、改めてMSゴシックのフォントファイルを入れてみます。



MSゴシックのインストール、そして宇宙へ

フォントファイルはここから入手できます。

msfont.zip

wgetコマンドを使って落として解凍するか、自分のPCに落として解凍してサーバーに上げるかすればオーケー。

上げる場所は「/usr/share/fonts」の下ならたぶんどこでも良い。「msfont」みたいなフォルダを作ってそこに入れれば良いと思う。

このzipファイルを解凍した場合、中に入っているのはttfじゃなくてttcっていう拡張子のファイルなんだけど、まあ特に問題はない。

そしたら、さっきと同じように、cidfmap.localっていうファイルを編集する。

# vi /etc/ghostscript/8.70/cidfmap.local

//以下を記述
/MS-PGothic << /FileType /TrueType /Path (/usr/share/fonts/msfont/msgothic.ttc) /SubfontID 1 /CSI [(Japan1) 3] >> ;

これで、エラーが出なくなり、PHPからコマンドを叩いても、無事にPDFが画像に変換されるようになりましたとさ。

今回はMSPゴシックだったけど、いろんなPDFを変換していれば、他のフォントで同じエラーが出ることは予想されます。

現時点で僕に分かる解決方法は、エラーが出るたびに同じ方法でフォントを追加して行くってことしか思いつかないけど……全体的に何とかする方法とかあるのかな?

むしろそういうのないと、全部に対応なんてできないよね……。ってことで、僕も探りを入れてみたいと思います。



※追記

僕と同じエラーで悩まされてる人は、もしかしたらこっちの方法で解決できるかもしれない。






ふいー、長い戦いでしたねー。

個々のエラーに関する記事ってのは見つかるんですけど、こんな風に全体を通して一つの記事になってるのってあんまないんで、あっち行ったりこっち行ったりになっちゃいますね。

まあ、こういう風にまとめていろんなエラーに襲われるっていうケース自体が、そんなにないからなんでしょうけどね。そこら辺は、僕の修行がまだまだ足りていないせいなんでしょう。

そりゃ足りなきゃエラーも出るさ。フォントが足りなければエラーが出るのと同じようにね。

ただ今回の場合は、msttcorefontsは別に入れなくても解決できたかもしれないね。必要だったのが別のフォントだったから。



あ、ところで。

冒頭にあるGIF画像の、左下のPDFからPNGのアイコンに変化してるやつって、この画像に似てない?

慣れるとどっち回りにも見えるんだよね

時計回りに見えるか反時計回りに見えるかで、右脳派か左脳派か診断できるってやつ。

僕としては、あのPDF⇔PNGの部分は時計回りをイメージして作成したんだけど、自分で見てても、反時計回りに見えることがあるわ。

「そもそも回ってるように見えないんだけど?」って言われちゃうと、元も子もないんすけどね^^;

確かにあれは、画像の幅を縮めたり広げたりしてるだけだからね……。

この画像みたいに、僕ももっとなめらかに動くGIFアニメーションが作れるようになりてーよ。
 もしかしたら何か関連しているかも? 
 質問や感想などお気軽にコメントしてください