九保すこひ@フリーランスエンジニア|累計300万PVのブログ運営中
さてさて、近年はウェブ開発の世界も成熟してきて、その昔は実行するには手間暇がかかり過ぎることでもいまだと簡単に実行できるようになってきました。
もちろん、PHPだけでは実行が難しい作業もたくさんありますが、サーバー内の他のプログラムと連携することで何の問題もなく開発できるため、ウェブだけでもデスクトップのような動きを実現することができたりします。
そこで、今回はそんな中からPDFをテキスト&画像ファイルに変換する方法をお届けしたいと思います。
ぜひ学習に役立ててくださいね。
※ 開発環境:Laravel 5.7 + Ubuntu 18.04 (通常のPHPでも実行できます)
目次
用意するもの
テキストが含まれたPDF。
もし手持ちがない場合は以下にサンプルを用意しましたので、そちらからダウンロードしてください。(中身は、夏目漱石の『吾輩は猫である』冒頭部分です)
ダウンロードしたら、storage/app/pdf
ファルダをつくり、そこへ移動させておいてください。
※ ちなみに、ファイルを移動させただけではPHP側から呼び出せない可能性があります。その場合はsudo chmod -R 777 storage
などで実行権限を与えておいてください。
PDFをテキストファイルに変換する
変換の流れ
PDFをテキストファイルに変換するには以下の流れになります。
- PDFからテキスト文章を抜き出す
- 抜き出したテキストをファイルに保存する
では実際にやってみましょう。
pdftotextをインストールする
今回の方法は、直接PHPでPDFを扱うのではなく、pdftotextというオープンソースをPHP側から呼び出して実行します。そのため、まずはpdftotext
をインストールしておきましょう。
まず、すでにインストールされているかをチェックします。
pdftotext -v
もしインストールされていたら、以下のようにバージョン情報が表示されることになります。
pdftotext version 0.62.0 Copyright 2005-2017 The Poppler Developers - http://poppler.freedesktop.org Copyright 1996-2011 Glyph & Cog, LLC
インストールされていない場合は次のコマンドで実行しましょう。
(Ubuntu
or Debian
)
sudo apt install poppler-utils
(Redhat
or CentOS
)
sudo yum install poppler-utils
パッケージをインストールする
PHPにはpdftotext
を簡単に利用できるパッケージが公開されているのでこれを利用します。インストールはcomposer
で一発です。
composer require spatie/pdf-to-text
PDFをテキストに変換する
では、まずはPDFからテキスト文章を抜き出す部分です。
$pdf_path = storage_path('app/pdf/wagahaihanekodearu.pdf'); $text = \Spatie\PdfToText\Pdf::getText($pdf_path);
$text
を<pre></pre>
タグで囲んで表示したものがこちらです。
なお、第2引数はコマンドラインのpdftotext
がある場所を指定することができます。もしうまくいかない場合は以下のコマンドを実行し、表示されたパスをこの引数に指定してみるといいでしょう。
which pdftotext
Pdf::getText($pdf_path, '/usr/bin/pdftotext');
また、第3引数ではpdftotext
のオプション情報を指定することができます。
今回の例で関連するオプションは以下のようになります。
- f ・・・ 開始ページを指定
- l ・・・ 終了ページを指定
- r ・・・ 解像度(DPI)。デフォルトは 72 DPI
- x ・・・ 切り抜きエリアのX座標
- y ・・・ 切り抜きエリアのY座標
- W ・・・ 切り抜きエリアの横幅
- H ・・・ 切り抜きエリアの高さ
- layout ・・・ できるだけ元のレイアウトでテキストを抽出する
- htmlmeta ・・・ HTMLとして出力。つまりHTMLタグが入る
- enc ・・・ 出力する文字コード。「Shift-JIS」「EUC-JP」など。 *1
- eol ・・・ 改行コードを指定。「unix」「dos」「mac」
- nopgbrk ・・・ 改ページを含まない。
- opw ・・・ 所有者のパスワード
- upw ・・・ ユーザーのパスワード
*1: pdftotext -listenc
とコマンド入力すると利用できる文字コードの一覧を確認することができます。
では、せっかくなので上のオプションx
、y
、W
、H
を使って範囲を指定し、ヘッダーやフッター情報を除去したテキストを取得してみましょう。
(イメージ)
コードはこうなります。
$text = Pdf::getText($pdf_path, '/usr/bin/pdftotext', [ 'x 0', // X座標 'y 30', // Y座標 'W 1000', // 横幅 'H 500' // 高さ ]);
実行結果です。
あとは、file_put_content()
を使ってテキストファイルを作成すれば変換は完了です。
$text_path = storage_path('app/text/wagahaihanekodearu.txt'); file_put_contents($text_path, $text);
PDFを画像に変換する
ImageMagickとGhostScriptをインストールする
PDFを画像に変換するにはImageMagick
とGhostScript
を利用します。
もし、以下のコマンドでチェックして見つからない場合はインストールしておきましょう。
- gs -v ・・・ GhostScriptのバージョンチェック
- convert -v ・・・ ImageMagickのバージョンチェック
(Ubuntu
もしくはDebian
)
sudo apt install ghostscript sudo apt install imagemagick
(Redhat
もしくはCentOS
)
sudo yum install ghostscript sudo yum install ImageMagick
パッケージをインストールする
こちらのパッケージもcomposer
一発で完了します。
composer require spatie/pdf-to-image
PDFを画像へ変換する
では、実際のコードです。
$pdf_path = storage_path('app/pdf/wagahaihanekodearu.pdf'); $pdf = new \Spatie\PdfToImage\Pdf($pdf_path); $image_path = storage_path('app/images/wagahaihanekodearu.jpg'); $pdf->saveImage($image_path);
まずはPdfToImage
にPDFのパスを入れてインスタンスをつくり、さらにsaveImage()
で保存場所を指定するだけです。とてもシンプルですね。
実際に作成したJPEG画像です(ただし、縮小してます)
もし以下のようなエラーが表示された場合はImageMagick
がPDFを使える設定になっていません。
ImagickException (499) not authorized `******.pdf' @ error/constitute.c/ReadImage/412
この場合は、ImageMagick
がインストールされているフォルダ内のpolicy.xml
(例:/etc/ImageMagick-6/policy.xml
)を開いて以下の部分を変更しましょう。
<policy domain="coder" rights="none" pattern="PDF" />
↓↓↓ 変更する
<policy domain="coder" rights="read|write" pattern="PDF" />
そして、大事なのがウェブサーバーを再起動することです。nginx
+ php-fpm
の場合は両方再起動しましょう。
sudo systemctl restart apache
sudo systemctl restart nginx
sudo systemctl restart php7.2-fpm
などなど。
様々なオプション
PdfToImage
には色々なオプションが利用できるようになっています。
ひとつずつ見ていきましょう。
ページ番号を指定する
画像に変換したいページ番号を指定することができます。
$pdf->setPage(2); // PDFの2ページ目だけ変換
画像形式を指定する
保存する画像形式を指定することができます。
$pdf->setOutputFormat('png'); // pngで保存
※ ただし指定できるのは、jpg
, jpeg
, png
の3種類だけで、デフォルトはjpg
です。
画質を指定する
保存する画像の画質を指定することができます。
$pdf->setCompressionQuality(100);
解像度を指定する
画像の解像度を指定することができます。
$pdf->setResolution(144);
画像のレイヤーを合成する
$pdf->setLayerMethod(\imagick::LAYERMETHOD_COALESCE);
利用できるパラメータは、以下のとおりです。
- imagick::LAYERMETHOD_UNDEFINED
- imagick::LAYERMETHOD_COALESCE
- imagick::LAYERMETHOD_COMPAREANY
- imagick::LAYERMETHOD_COMPARECLEAR
- imagick::LAYERMETHOD_COMPAREOVERLAY
- imagick::LAYERMETHOD_DISPOSE
- imagick::LAYERMETHOD_OPTIMIZE
- imagick::LAYERMETHOD_OPTIMIZEPLUS
- imagick::LAYERMETHOD_OPTIMIZEIMAGE
- imagick::LAYERMETHOD_OPTIMIZETRANS
- imagick::LAYERMETHOD_REMOVEDUPS
- imagick::LAYERMETHOD_REMOVEZERO
- imagick::LAYERMETHOD_COMPOSITE
- imagick::LAYERMETHOD_MERGE
- imagick::LAYERMETHOD_FLATTEN
- imagick::LAYERMETHOD_MOSAIC (integer)
その他
PDFのページ数を取得する
セットしたPDFのページ数を取得することができます。
$pdf->getNumberOfPages(); // ページ数を取得
画像の形式をサポートしているかチェックする
if(!$pdf->isValidOutputFormat('gif')) { echo 'この形式はサポートしていません。'; }
ImageMagickのインスタンスを取得する
$imagick = $pdf->getImageData();
今回のソースコードをダウンロード
実際今回の開発で使ってプログラム・コードを以下からダウンロードすることができます。
※ ただし、ImageMagick
などのインストールは各自で行ってください。