モーグルとカバとパウダーの日記

モーグルやカバ(EXカービング)山スキー(BC)などがメインの日記でした。今は仕事のコンピュータ系のネタが主になっています。以前はスパム対策関連が多かったのですが最近はディープラーニング関連が多めです。

PHPでImageMagickを使う時のトラブルと解決方法

PHP + ImageMagickってだけで、バッドノウハウの香りがぷんぷん漂ってくるような取り合わせだが、やっぱ謎な知識が必要だったのでメモ。


Windows上のxamppの環境で、PHPImageMagickを使ってPDFを画像に変換するという必要がありました。
CakePHPでUploadPackを使ってアップロードされたPDFファイルを、画像のサムネイル表示をさせたいのです。

ImageMagickWindows環境に導入するのも結構たいへんなのだけど、普通にPDFを画像にするだけでも、いくつかオプション指定してあげないと、背景が黒くなったりしてうまく表示が出来なかったのでした。


ImageMagickをインストールすると convert というコマンドライン用のexeが入るのだが、まずはこれを使って必要なオプションなどを確認すると良いようです。

前記のPDFを画像に変換する場合、下記オプションをつけるのがおすすめらしい。

> convert input.pdf -resize 600 -background white -flatten -alpha off output.jpg

これで、背景色白で横600pxにリサイズされた画像の出力が出来ます。


(参考)
とらりもん - Imagemagick
imagemagickのバッドノウハウ・PDFを画像にする編 - だけどこんなところで待っているよりは


さて、これをPHPImageMagickを使って実装した完成形はこのようになりました。

<?php
$im = new Imagick('C:\xampp\htdocs\input.pdf');
$im->setResourceLimit(6, 1);
$im->setIteratorIndex(0);
$im->setImageFormat('jpg');
$im->setBackgroundColor('white');
$im->thumbnailImage(600, 600, true);
$im = $im->flattenImages();
$im->setImageAlphaChannel(imagick::ALPHACHANNEL_DEACTIVATE);
$im->writeImage('C:\xampp\htdocs\output.jpg');


ここで「flattenImages」の部分

$im = $im->flattenImages();

を他の行と同様に「$im->flattenImages()」と書いてしまうと、なにも起こらないので注意する必要があります。
ちなみに「setflatternImages」は存在しません。うーむ… と思うけど、まあPHPだしね。flatternImagesは複数レイヤーを一つにまとめてしまう操作なので、非可逆だからこのような使いかたになっていると思われます。最初、それに気が付かずにPHPをdisってしまってすみません…


(参考)
Problem with Image Magick thumbnaill background colour


また普通に「setResourceLimit」の設定をしないで書くと、画像変換は行われるのだけども「Segmentation fault」が起こるという問題に悩まされることになると思います。

これはどうやらOpenMPに関連した問題らしく、Linuxなど手軽にImageMagickをリコンパイル出来る環境では、--disable-openmpOpenMPを切ったImageMagickを再構築してしまうのが良いらしい。


(参考)
kasahi memo: ImageMagick(imagik)がsegmentation faultするようになってしまった。


ただ、今回の場合はWindows環境でリコンパイルがめんどくさそうだったため、他の解決法を探しました。

すると下記エントリーより、「setResourceLimit(6, 1)」と設定することで THREAD_LIMIT の設定を1にすることが出来るそうで、これでOpenMPの問題を回避できることがわかりました。


(参考)
PHP5.3 + ImagickでSegmentation faultが出たときの対処法 - DQNEO起業日記

// 6はTHREAD_LIMITを意味するマジックナンバーだそうです。

ということで、うーむむ… という感じだが、まあPHPだしね。
こちらのエントリー書かれた @DQNEO さんにたいへん感謝です。


あと、メソッドの呼び方によってだいぶ処理速度が変わってくるような感じで、ベストプラクティスがあるようなのですが、まだ良くわかってないので、後日追記することになるかもしれません。


(追記)

DLL組み込んでPHPから直でImageMagick関数呼ぶ使い方だと、ghostscriptをコマンドから呼び出したときより

  • CMYK画像の場合、透明色の扱いがおかしくて色ズレが起きる
  • 画質が悪くなる
  • 処理速度が遅くなる

という問題が起きました。

そのため、ghostscriptを外部コマンド呼び出しで使うように後で修正しています。


CakePHPのUploadPackにPDFの画像化とサムネイル生成対応
http://d.hatena.ne.jp/stealthinu/20141224/p1


(関連)

WindowsでxamppのPHPImageMagickをインストール - モーグルとカバとパウダーの日記
http://d.hatena.ne.jp/stealthinu/20130709/p1