PHPでExif情報を表示する

(1/1)
スマホやデジカメで撮影された画像データには、撮影日時に加え、位置情報(緯度・経度)、絞り、シャッター速度、カメラの機種名、メーカー名など、さまざまな情報が Exif (エグジフ) (Exchangeable image file format) と呼ばれるタグ情報となって埋め込まれている。対応している画像フォーマットは JPEG、TIFF、PNGだ。
今回はPHPを使い、、JPEG画像ファイルから Exif情報を取り出すプログラムを作ってみることにする。

(2024年10月13日)文字化けデータを16進数で表示するようにした

目次

準備

PHPには、Exif情報を取得する  exif_read_data  関数が用意されている。この関数を利用するのにGDライブラリは不要だが、--enable-exif を enable にして PHPをコンパイルする必要がある。配布されている Windows バイナリの場合、extension に php_exif.dll を指定してやるだけで利用できるようになる。ただし、かならず php_mbstring.dll の後に読み込む必要がある。つまり、php.ini の定義は、かならず下記の順番にしておく必要がある。
extension=php_mbstring.dll
extension=php_exif.dll
では、任意の画像ファイルの Exif 情報を表示するPHPプログラムを紹介する。

サンプル・プログラムの実行例

PHPでExif情報を表示する

サンプル・プログラム

圧縮ファイルの内容
printexif.phpサンプル・プログラム本体。
printexif.php 更新履歴
バージョン 更新日 内容
3.0.1 2024/10/13 文字化けデータを16進数で表示するようにした
3.0 2022/02/19 PHP8対応,全面改訂
2.0 2009/10/23 ネット上の画像に対応
1.1 2009/01/26 PHP5対応,ファイルサイズチェック
1.0 2005/09/20 初版

解説:Exif情報を配列に格納する

printexif.php

 190: /**
 191:  * Exif情報を配列に格納する(下請け関数)
 192:  * @param   String $fname 画像ファイル名
 193:  * @param   Array  $exif  Exif情報を格納する配列
 194:  * @return  0:正常に表示した
 195:  *          (-1): ファイルが存在しない
 196:  *          (-2): JPEG/TIFF以外の形式
 197:  *          (-3): Exif情報がない
 198: */
 199: function _getexif($fname, &$exif) {
 200:     //ファイルの存在チェック
 201:     if (fopen($fname, 'rb') == FALSE)   return (-1);
 202: 
 203:     //JPEG/TIFFの型チェック
 204:     switch (exif_imagetype($fname)) {
 205:         case IMAGETYPE_JPEG:
 206:         case IMAGETYPE_TIFF_II:
 207:         case IMAGETYPE_TIFF_MM:
 208:             break;
 209:         default:
 210:             return (-2);
 211:     }
 212: 
 213:     //Exif情報を配列へ
 214:     if (($cls = exif_read_data($fname, 'EXIF')) == FALSE) {
 215:         return (-3);
 216:     }
 217:     foreach ($cls as $key=>$sect) {
 218:         if (is_array($sect) == FALSE) {
 219: //          $exif[$key] = $sect;
 220:             $ss = (string)$sect;
 221:             if (preg_match('/[\x20-\x7E]/i', substr($ss, 0, 1)) == 0) {
 222:                 $exif[$key] = @bin2hex($sect);
 223:             } else {
 224:                 $exif[$key] = $ss;
 225:             }
 226:         } else {
 227:             foreach($sect as $name=>$val) {
 228:                 $exif[$key . '.' . $name] = $val;
 229:             }
 230:         }
 231:     }
 232:     return 0;
 233: }

このプログラムの主役は、ユーザー定義関数 _getexif である。引数は、ファイル名(URLも可能)と、Exif 情報を格納するための配列変数の2つ。

まず、ファイルが存在するかどうか調べる。
次に、そのファイルがJPEGかTIFFであるかどうか調べる。このような目的のために、PHPには  exif_imagetype  という関数が用意されている。
これらをクリアして、はじめて  exif_read_data  関数を使って Exif 情報を読み出す。
なお、Exif 情報がない場合は、  exif_read_data  関数は FALSE を返すので、このエラーもキャッチしておく必要がある。

Exif情報はオブジェクト構造をしている。そこで、配列の添え字にタグ名、配列の中身として値を格納することにする。
これを実現するために、二段構えの foreach 構文で情報を配列へ展開している。
なお、タグ名の一部はデジカメ固有の文字列なので注意が必要だ。詳細はこちら

後述するが、php_exif.dll は最新のExif規格に準拠していないため、undefinedを表示するタグが増えている。また、データも正しい形式に変換されずに文字化けを起こしているので、 preg_match 関数と  bin2hex 関数を使い、印字不能な文字が入っているときには16進表記にするように改良した。

Exif規格

Exif規格 は、富士フイルムが開発し、1995年(平成7年)にCIPA(一般社団法人カメラ映像機器工業会)と JEITA(電子情報技術産業協会)が規格化した。最新バージョンは2019年(平成31年)5月に改訂された2.32で、CIPAのサイトでドラフト版を読むことができる。
改定履歴を読むと、2000年代に入っても改良が続いているのだが、現在PHPに同梱されている php_exif.dllは最新の仕様に対応していない。このため、undefined と表示されるタグが増えている。

DateTimeタグは、長らくローカル時間しか記録できなかったが、バージョン2.31(2016年7月)になり、ようやく、UTCとの時差を記録する OffsetTimeタグが追加になった。
PHPでExif情報を表示する
本プログラムで UndefinedTag:0x9010 と表示されているのが、UTCとの時差を記録する OffsetTimeタグである。UndefinedTag:0x9011DataTimeOriginalタグに対する時差を、UndefinedTag:0x9012DataTimeDigitizedタグに対する時差を、それぞれ示している。

printexif.php

 235: /**
 236:  * Exif情報を配列に格納する
 237:  * @param   string $url   画像ファイルURL
 238:  * @param   string $fname 画像ファイル(ローカル)
 239:  *                  $url, $fname いずれか一方を渡す
 240:  * @param   array  $exif    Exif情報を格納する配列
 241:  * @param   string $errmsg  エラーメッセージ
 242:  * @return  なし
 243: */
 244: function getexif($url, $fname, &$exif, &$errmsg) {
 245:     //Exif情報の取得 - ネット上
 246:     if ($url !'') {
 247:         $fname = $url;
 248:         $arr   = array();
 249:         $ret   = _getexif($fname, $exif);
 250:     //Exif情報の取得 - ローカルファイル
 251:     } else if ($fname !'') {
 252:         $arr = array();
 253:         $ret = _getexif($fname, $exif);
 254:     }
 255: 
 256:     //結果判断
 257:     $errmsg = '';
 258:     switch ($ret) {
 259:         case 0:
 260:             $errmsg = '';
 261:             break;
 262:         case (-1):
 263:             $errmsg = 'ファイルが存在しません';
 264:             break;
 265:         case (-2):
 266:             $errmsg = 'ファイル形式がJPEG/TIFF以外です';
 267:             break;
 268:         case (-3):
 269:             $errmsg = 'Exif情報がありません';
 270:             break;
 271:         case (-4):
 272:             $errmsg = 'ファイルサイズが大きすぎます';
 273:             break;
 274:         default:
 275:             $errmsg = 'ファイル名またはURLを入力してください';
 276:             break;
 277:     }
 278: }

ユーザー定義関数 getexif は、画像ファイルURL、画像ファイル(ローカル)のいずれか一方を引数とし、先ほどのユーザー定義関数 _getexif を呼び出し、Exif情報を格納した配列とエラー・メッセージを返す。

参考サイト

(この項おわり)
header