ImageMagickとPHPを用いてPDFを画像変換する

# はじめに
## ■目的
ImageMagick と PHP。
そしてPHPからImageMagickを利用するためのPHP 拡張モジュールImagick。
これらを利用することでPHPスクリプトから画像変換が出来ます。

しかし、これだけではPDFから画像変換が出来ません。
そこでGhostscriptを導入しPDFの画像変換を行ってみました。

## ■Ghostscriptとは
PostScript/PDF インタプリタ。
よく分かりませんが、アドビシステムズのPostScriptファイルを画像ファイルに変換することが出来るもののようです。
こちらを導入することでImageMagick+PHPでPDFより画像変換が可能となるとのこと。

■公式サイト
http://www.ghostscript.com/


## ■今回の実装環境
CentOS `6.5 (64bit)`
php `5.4.33`
httpd `2.2.15`
ImageMagick `6.5.4.7`
imagick `3.1.2`

# 00. 事前準備
▽コンパイルに必要なパッケージの導入状況確認

```bash
# rpm -qa | grep "make\|gcc"
libgcc-4.4.7-4.el6.x86_64
gcc-c++-4.4.7-4.el6.x86_64
make-3.81-20.el6.x86_64
gcc-4.4.7-4.el6.x86_64
```

無ければインストール

```bash 
# yum install make gcc
```

もしくは、開発ツール一括インストール

```bash 
# yum groupinstall 'Development tools'
```


▽GhostScript導入に必要なパッケージが入っているか確認

```bash 
# rpm -qa | grep "libXt-devel"
libXt-1.1.4-6.1.el6.x86_64
```

# 01.インストール
■ソース配布元
公式サイトより、Ghostscript 9.15 Source for all platforms の リンクを取得 (2015/01/01時点の最新版)
http://downloads.ghostscript.com/public/ghostscript-9.15.tar.gz

```bash 
# cd /usr/local/src/
# curl -OL http://downloads.ghostscript.com/public/ghostscript-9.15.tar.gz
# tar -zxvf ghostscript-9.15.tar.gz
# cd ghostscript-9.15
# ./configure --disable-compile-inits --with-x --with-drivers=ALL --without-luratech --with-libiconv=gnu --prefix=/usr/local
※オプション「--disable-compile-inits」を指定しないと、インストール後の設定変更ができなくなるとのこと

(省略)

Libtiff is now configured for x86_64-unknown-linux-gnu

  Installation directory:             /usr/local
  Documentation directory:            ${prefix}/share/doc/tiff-4.0.1
  C compiler:                         gcc -g -O2 -Wall -W
  C++ compiler:                       g++ -g -O2
  Enable runtime linker paths:        no
  Enable linker symbol versioning:    no
  Support Microsoft Document Imaging: yes
  Use win32 IO:                       no

 Support for internal codecs:
  CCITT Group 3 & 4 algorithms:       yes
  Macintosh PackBits algorithm:       yes
  LZW algorithm:                      yes
  ThunderScan 4-bit RLE algorithm:    yes
  NeXT 2-bit RLE algorithm:           yes
  LogLuv high dynamic range encoding: yes

 Support for external codecs:
  ZLIB support:                       yes
  Pixar log-format algorithm:         yes
  JPEG support:                       yes
  Old JPEG support:                   yes
  JPEG 8/12 bit dual mode:            no
  ISO JBIG support:                   no
  LZMA2 support:                      no

  C++ support:                        yes

  OpenGL support:                     no

(省略)

configure: WARNING: Unable to include opvp/oprp driver due to missing or disabled prerequisites...
configure: WARNING: Unable to include opvp/oprp driver due to missing iconv/libiconv...

※上記、configure中に気になったメッセージ抜粋 → この後、問題となることはありませんでした。
```

```bash
# make
# make install
```
これでインストール完了です。

# 02.設定
## ■02-1a. 日本語を扱えるようにする(IPAフォント、IPAexフォント インストール)

■IPA独立行政法人 (配布元)
http://ipafont.ipa.go.jp/ipafont/download.html

```bash 
# cd /usr/local/src
# mkdir font
# cd font
# wget 'http://dl.ipafont.ipa.go.jp/IPAexfont/IPAexfont00201.zip'
# wget 'http://dl.ipafont.ipa.go.jp/IPAfont/IPAfont00303.zip'
# unzip IPAfont00303.zip
  inflating: IPAfont00303/ipag.ttf
  inflating: IPAfont00303/ipagp.ttf
  inflating: IPAfont00303/ipam.ttf
  inflating: IPAfont00303/ipamp.ttf

# unzip IPAexfont00201.zip
  inflating: IPAexfont00201/ipaexg.ttf
  inflating: IPAexfont00201/ipaexm.ttf

# mkdir -p /usr/share/fonts/ipa/TrueType/
# cp -p ./IPAexfont00201/*.ttf /usr/share/fonts/ipa/TrueType/.
# cp -p ./IPAfont00303/*.ttf /usr/share/fonts/ipa/TrueType/.
# ls -l /usr/share/fonts/ipa/TrueType/
ipaexg.ttf
ipaexm.ttf
ipag.ttf
ipagp.ttf
ipam.ttf
ipamp.ttf
```

```bash 
・フォントキャシュクリア
# fc-cache -fv

・フォント一覧で名称を確認
# fc-list | grep -i ipa
IPAexゴシック,IPAexGothic:style=Regular,Regulare
IPAゴシック,IPAGothic:style=Regular
IPA Pゴシック,IPAPGothic:style=Regular
IPAex明朝,IPAexMincho:style=Regular
IPA明朝,IPAMincho:style=Regular
IPA P明朝,IPAPMincho:style=Regular
```

## ■02-1b. msttcorefontsをインストール

▽配布元(インストール方法も記載アリ)
An easy way to install Microsoft's TrueType core fonts on linux
http://corefonts.sourceforge.net/

1) 必要なパッケージ
・rpm-build
・ttmkfdir
・cabextract (http://www.cabextract.org.uk )

```bash 
# yum install rpm-build ttmkfdir

# cd /usr/local/src/
# wget http://www.cabextract.org.uk/cabextract-1.4-1.src.rpm
# rpmbuild --rebuild cabextract-1.4-1.src.rpm
# rpm -ivh /root/rpmbuild/RPMS/x86_64/cabextract-1.4-1.x86_64.rpm
※buildしたrpmファイルは、「$HOME/rpmbuild/RPMS/x86_64/」配下に格納される
```

2) specファイルより msttcorefonts インストール

```bash 
# cd /usr/local/src/
# wget http://corefonts.sourceforge.net/msttcorefonts-2.5-1.spec
# rpmbuild -bb msttcorefonts-2.5-1.spec
# rpm -ivh /root/rpmbuild/RPMS/noarch/msttcorefonts-2.5-1.noarch.rpm
※buildしたrpmファイルは、「$HOME/rpmbuild/RPMS/noarch/」配下に格納される

・インストール先は以下
/usr/share/fonts/msttcorefonts/*.ttf
```

## ■02-2. cidfmap
・CIDフォントと実際のTrueType（OpenType）フォントとの対応を指定する設定ファイル。
最下行に使用するフォント、フォントへのパスを追記。

```bash 
# cd /usr/local/share/ghostscript/9.15/Resource/Init
# cp -p cidfmap cidfmap.org
```

```bash 
# vi cidfmap
----------
/Ryumin-Light         /IPAEXMincho      ;
/GothicBBB-Medium     /IPAGothic        ;
/HeiseiMin-W3         /Ryumin-Light     ;
/HeiseiKakuGo-W5      /GothicBBB-Medium ;

%%% Alias for dvips
/ipamincho    /IPAMincho ;
/ipapmincho   /IPAPMincho ;
/ipagothic    /IPAGothic ;
/ipapgothic   /IPAPGothic ;
/ipam         /IPAMincho ;
/ipamp        /IPAPMincho ;
/ipag         /IPAGothic ;
/ipagp        /IPAPGothic ;
/ipaexm       /IPAEXMincho ;
/ipaexg       /IPAEXGothic ;

/IPAMincho
<<
/FileType /TrueType
/CSI [(Japan1) 6]
/Path (/usr/share/fonts/ipa/TrueType/ipam.ttf)
/SubfontID 0
>> ;

/IPAPMincho
<<
/FileType /TrueType
/CSI [(Japan1) 6]
/Path (/usr/share/fonts/ipa/TrueType/ipamp.ttf)
/SubfontID 0
>> ;

/IPAGothic
<<
/FileType /TrueType
/CSI [(Japan1) 6]
/Path (/usr/share/fonts/ipa/TrueType/ipag.ttf)
/SubfontID 0
>> ;

/IPAPGothic
<<
/FileType /TrueType
/CSI [(Japan1) 6]
/Path (/usr/share/fonts/ipa/TrueType/ipagp.ttf)
/SubfontID 0
>> ;

/IPAEXMincho
<<
/FileType /TrueType
/CSI [(Japan1) 6]
/Path (/usr/share/fonts/ipa/TrueType/ipaexm.ttf)
/SubfontID 0
>> ;

/IPAEXGothic
<<
/FileType /TrueType
/CSI [(Japan1) 6]
/Path (/usr/share/fonts/ipa/TrueType/ipaexg.ttf)
/SubfontID 0
>> ;

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

## ■02-3. gs_res.ps
・Ghostscriptが参照する様々なリソース（ファイル等）の場所を指定するファイル。
インストールした環境に合わせて適切に修正する。具体的には、319行目の/FontResourceDirと321行目の/GenericResourceDirを編集する

```bash
# cd /usr/local/share/ghostscript/9.15/Resource/Init
# cp -p gs_res.ps gs_res.ps.org
# vi gs_res.ps
------
%   /FontResourceDir (Font) .resource_dir_name
   /FontResourceDir (/usr/local/share/ghostscript/9.15/Resource/Font/) .resource_dir_name

%  /GenericResourceDir () .resource_dir_name
  /GenericResourceDir (/usr/local/share/ghostscript/9.15/Resource) .resource_dir_name
```

## 03.動作確認

■参考サイト
[公式] How to use Ghostscript
http://www.ghostscript.com/doc/current/Use.htm

■実行ファイルの場所

```bash 
# which gs
/usr/local/bin/gs
```

■コマンドの基本書式

```bash 
# gs [オプション] [入力ファイル]
```

## ■03-1. PDFファイルを作成する

・サンプル画像(tiger.eps)を利用してPDFファイルを作成する

```
# cd /usr/local/share/ghostscript/9.15/examples
# gs -sDEVICE=pdfwrite -sOutputFile=tiger.pdf tiger.eps
>>showpage, press <return> to continue<<　←エンター押下
GS>
GS>quit
```

````
# ls -l tiger.pdf
tiger.pdf
````

▽オプションの説明

```
ヘルプの内容を記載しただけです
-sDEVICE=[出力デバイス] ※DEVICEとなっているが、今回はPNGやJPEGなどの画像形式を指定
-sOutputFile=[出力ファイル名]
-dBATCH ※プロンプトを自動的に抜け処理を実行してくれる
-r[解像度] ※デフォルトは72dpi
-g<width>x<height> ※page size in pixels
```

# 04. ImageMagick & Imagick との連携

## ■04-1. 実装

■参考URL
[公式] 画像処理 (ImageMagick)
http://php.net/manual/ja/book.imagick.php


■まずyumで「ImageMagick」「ImageMagick-devel」をインストール

```
# yum install ImageMagick ImageMagick-devel
```

■peclを使えるようにする

```
# yum install php-pear php-devel httpd-devel
```

■PECLで「imagick」インストール

```
# pecl install imagick
Please provide the prefix of Imagemagick installation [autodetect] :　そのままエンターで自動的にImageMagickを探してもらう
```

■php.iniの設定

・imagickを有効にする

```
# cp -p /etc/php.ini /etc/php.ini.org
# vi /etc/php.ini
------
extension=imagick.so　こちらを追記
```

■PHPモジュールとして追加されていることを確認

```
# php -m | grep imagick
imagick
```

## ■04-2. 動作確認

■まずコマンドラインより
・Tiger.pdfをPNGファイルに変換する。

```
# cd /usr/local/share/ghostscript/9.15/examples
# convert tiger.pdf tiger.png
# ls tiger.png
tiger.png
```

![tiger.png](https://qiita-image-store.s3.amazonaws.com/0/50310/6a730167-94ab-ab94-67db-c28a9dec7197.png)

<div style="text-align: center;">tiger.png</div>

・複数ページあるannots.pdfをPNGファイルに変換する

```
# convert annots.pdf annots.png
# ls annots*.png
annots-0.png  annots-1.png  annots-2.png  annots-3.png  annots-4.png  annots-5.png
※ページ毎に画像ファイルへ変換される
```

![annots-1.png](https://qiita-image-store.s3.amazonaws.com/0/50310/0861b0fc-bc0a-cdf5-e66b-31e81e2d77cd.png)
<div style="text-align: center;">annots-1.png</div>


■スクリプトより実行

・apacheで書き込みが出来るよう権限付与しておく

```
# cd /var/www/html
# mkdir /var/www/html/pdf
# chown root.apache /var/www/html/pdf
# chmod 775 /var/www/html/pdf
```

・PDFファイルの全ページを画像に変換するスクリプトを用意

```
# vi /var/www/html/pdf/Imagick-Ghostscript.php
```

```php 
<?php

//ImageMagic定義
$im = new imagick();
//$im->setResolution(144,144);

//対象のディレクトリを指定(カレントディレクトリ);
$serch_dir = dirname(__FILE__);

$files = new RecursiveIteratorIterator(
            new RecursiveDirectoryIterator($serch_dir,
                    FilesystemIterator::CURRENT_AS_FILEINFO |
                    FilesystemIterator::KEY_AS_PATHNAME |
                    FilesystemIterator::SKIP_DOTS
            )
        );

// 拡張子がpdfのファイルのみ抽出
$files = new RegexIterator($files, '/^.+\.pdf$/i', RecursiveRegexIterator::MATCH);

foreach($files as $file_path => $file_info) {
//    echo 'file name : '. basename($file_path)          .PHP_EOL; //ファイル名
//    echo 'file path : '. $file_path                    .PHP_EOL; //ファイルのフルパス
//    echo 'file size : '. $file_info->getSize()         .PHP_EOL; //ファイルサイズ
//    echo 'contents  : '. file_get_contents($file_path) .PHP_EOL; //ファイルの内容を取得
//    echo 'serch dir : '. $serch_dir                    .PHP_EOL; //

      //ファイル名のみ取得
      $file_name = basename($file_path);
      $reg="/(.*)(?:\.([^.]+$))/";
      preg_match($reg,$file_name,$retArr);
      $file_name  = $retArr[1];
      $extension  = $retArr[2];

      //ImageMagic処理
      //im->readimage($file_path);
      //$page_count = $im->getImageScene();

      //PDFから画像ファイルへの変換処理
      $output = shell_exec("convert ".$file_path." ".$serch_dir."/".$file_name.".png 2>&1");
      print_r ($output);

//      for($i = 0; $i <= $page_count-1; $i++) {
//          $im->setIteratorIndex($i);
//          $im->setImageFormat('png');
//          $im->writeimage($serch_dir.'/'.$file_name . $i . "png");
//      }

}

$im->clear();

?>
```

■動作確認
・ブラウザよりアクセス
http://(IP or Domain)/Imagick-Ghostscript.php

・コマンドラインより実行

```
# chmod 775 /var/www/html/pdf/Imagick-Ghostscript.php
# chown root.apache /var/www/html/pdf/Imagick-Ghostscript.php
# php /var/www/html/pdf/Imagick-Ghostscript.php
```

問題なく変換することが出来ました。

# 05.おまけ

## ■05-1. 公式非推奨とされているImagickモジュール
1) Imagick::setImageIndex
http://php.net/manual/ja/imagick.setimageindex.php

2) destroy();
http://php.net/manual/ja/imagick.destroy.php
→代替 Imagick::clear


## ■05-2. webサーバからスクリプトを実行した際に古いgsが呼び出されエラーとなった場合
※どのタイミングかは分かりませんが、GhostScript 8.7が最初からインストールされているとこの現象が発生するようです。

```
# view /var/log/httpd/error_log
----------
GPL Ghostscript 8.70: Unrecoverable error, exit code 1 ★バージョンが古い
convert: Postscript delegate failed `./sample.pdf': No such file or directory @ pdf.c/ReadPDFImage/611.
convert: missing an image filename `./sample_thumb.jpg' @ convert.c/ConvertImageCommand/2800.
```

▽対処：シンボリックリンクを貼る
・今回導入した最新版が実行されるようシンボリックリンクを貼ることで対処

```
# ln -sb /usr/local/bin/gs /usr/bin/gs
----------
lrwxrwxrwx 1 root root 17  1月  5 22:36 2015 /usr/bin/gs -> /usr/local/bin/gs
```


以上になります。