準備
extension=php_mbstring.dllでは、任意の画像ファイルの Exif 情報を表示するPHPプログラムを紹介する。
extension=php_exif.dll
サンプル・プログラムの実行例

サンプル・プログラム
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: }

まず、ファイルが存在するかどうか調べる。
次に、そのファイルが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規格
改定履歴を読むと、2000年代に入っても改良が続いているのだが、現在PHPに同梱されている php_exif.dllは最新の仕様に対応していない。このため、undefined と表示されるタグが増えている。

DateTimeタグは、長らくローカル時間しか記録できなかったが、バージョン2.31(2016年7月)になり、ようやく、UTCとの時差を記録する OffsetTimeタグが追加になった。

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: }
参考サイト
- Exif 2.32 ドラフト版
- PHPで撮影場所をマッピング:ぱふぅ家のホームページ
- C++ で撮影場所をマッピング:ぱふぅ家のホームページ
- 配布ファイルに個人情報を残さない:ぱふぅ家のホームページ
- SNSにアップした写真から住所が漏れる:ぱふぅ家のホームページ
今回はPHPを使い、、JPEG画像ファイルから Exif情報を取り出すプログラムを作ってみることにする。
(2024年10月13日)文字化けデータを16進数で表示するようにした