PHP で EXIF を読む 3
PHP で EXIF を読むシリーズその 3。これまでの記事で PHP による EXIF 読み込み方法として PEL というライブラリを紹介し、使用上の問題点と解決策を検討した。
しかし本日、「PEL のカレンダー関数依存を解決する」のコメントとして makoto_kw 氏に「PEL へ変更を加えないで済む方法」についてアドバイスをいただいた。
新しい対策の有効性を確認したので、前の記事を修正しようと思ったが、以前に公開した EXIF 読み込みのサンプルも修正したくなったので、これらをまとめて新しい記事にする事にした。
PEL による EXIF 読み込み
PEL とは、オープンソースの PHP 向け EXIF 編集ライブラリ。現在は GitHub から入手できる。
PEL のフォルダーを pel
とした場合、EXIF 読み込みの処理は以下のようになる。
<?php
require_once( "pel/PelJpeg.php" );
/**
* 画像から読み取った IFD 情報を取得します。
*
* @param $url 画像の URL。
*
* @return 成功時は IFD 情報。失敗時は false。
*/
function getIfd( $url )
{
try
{
$jpeg = new PelJpeg( $url );
$app1 = $jpeg->getExif();
if( !$app1 ) { return false; }
$tiff = $app1->getTiff();
if( !$tiff ) { return false; }
return $tiff->getIfd();
}
catch( Exception $e )
{
return false;
}
}
/**
* 画像から読み取った撮影日時を取得します。
*
* @param $url 画像の URL。
*
* @return 成功時は撮影日時。失敗時は false。
*/
function readDateTime( $url )
{
$ifd = getIfd( $url );
if( !$ifd ) { return false; }
$v = $ifd->getEntries();
if( !isset( $v[ PelTag::DATE_TIME ] ) ) { return false; }
return $v[ PelTag::DATE_TIME ]->getText();
}
// 撮影日時を出力
$datetime = readDateTime( "http://***/test.jpg" );
echo $datetime;
?>
基本的に IFD や GPS を表すエントリのオブジェクトを参照し、それらの持つデータを getEntries
メソッドで配列として取得。配列の添え字は PelTag
クラスに定数として定義されているので、これを使用する。
添え字でアクセスした要素はデータ種別により文字列やバイナリ、配列などに分かれる。これらは EXIF の規格や Eclipse のデバッガなどで構造を確認しながら操作する。
PEL のカレンダー関数依存
PHP 用の EXIF 操作ライブラリ PEL は PHP の拡張モジュールに含まれるカレンダー関数に依存している。Windows 版の PHP は初めから拡張モジュールを提供しているが、その他の仕向けでは -enable-calendar
オプション付きでコンパイルするか自前で拡張モジュールを入れて php.ini を編集しなければならない。
サーバー運営者ならこれらの対応を行う事も可能だろう。しかしレンタル サーバー利用者では対応は難しいか不可能。そこでカレンダー関数の Wrapper となる PHP スクリプトを作成して PEL よりも先にインクルードすることで依存を吸収する。
まず Wrapper となるスクリプトを作成する。php-calender-patch.php というファイル名で以下のように実装。
<?php
class CalendarUtility
{
static public function gregoriantojd( $month, $day, $year )
{
// gregoriantojd 相当の処理
}
}
if( !function_exists( gregoriantojd ) )
{
function gregoriantojd( $month, $day, $year )
{
return CalendarUtility::gregoriantojd( $month, $day, $year );
}
}
?>
CalendarUtility
というクラスにカレンダー関数の代替メソッドを定義する。処理は PHP 拡張モジュールのカレンダー関数 (C 言語) を移植。クラスにした理由は以下。
- 同一目的を持つ処理を局所化したかった
- 移植元の処理を見ると理解しやすいのだが public にしなくても済む処理がある
これを前提にグローバル スコープでカレンダー関数の定義を判定、未定義なら CalendarUtility
の代替メソッドを呼び出すようにする。この処理がなされると以降のカレンダー関数に対する呼び出しが以下のように変化する。
- カレンダー関数が定義されている場合はそれを使用
- カレンダー関数が未定義なら新たに定義された代替メソッドを使用
このスクリプトを PEL インクルードの前に置くことで PEL を変更せずにカレンダー関数への依存を解決できる。
サンプル プログラム
今回の記事で取り上げた処理の完全なソースを以下に公開する。
カレンダー関数の代替メソッド実装は PHP 拡張モジュールから移植したので、ライセンスはこれを踏襲して PHP License としておく。
サンプル プログラムの動作手順は以下のようになる。
- ダウンロードしたファイルを展開
- 展開されたファイルが php-calender-patch.php と test-read-exif.php の 2 つの PHP スクリプトである事を確認
- test-read-exif.php 内の readExif 関数の "http://***/test.JPG" という部分を、EXIF 情報を取得したい画像の URL に変更する
- PHP が動作するサーバー上にスクリプトを配置する
- PEL を格納した pel というフォルダをスクリプトと同じ階層に配置する
- test-read-exif.php へアクセスし、スクリプトを実行する
手順 3 の画像にアクセス可能で、EXIF 情報 ( このサンプルの場合、GPS と撮影日時 ) が設定されていれば、手順 6 を実行した時に画像情報が出力される。
Comments from WordPress
- anonymous 2010-03-20T14:35:34Z
サンプルファイルにアクセス出来ないようです...
再アップをお願いしてもよいでしょうか。
- akabeko 2010-03-20T15:04:18Z
恐らくサンプル プログラム ZIPのことだと思いますが、今、アクセスしたらダウンロードできました。もう一度、試してみてください。