PHPでExif情報を表示する(Windowsアプリ版)

(1/1)
デジカメで撮影された JPEG画像には、撮影日時に加え、絞り、シャッター速度、デジカメの機種名、メーカー名など、さまざまな情報が Exif と呼ばれるタグ情報となって埋め込まれている。最近の GPS 付携帯デジカメでは、緯度・経度情報まで記録されている。
これを PHP で取得するプログラムを「PHP で Exif 情報を表示する」で紹介した。このプログラムを Windows アプリに移植する。

サンプル・プログラム

PHPでWindowsアプリ開発:Exif情報

準備

画像ファイルと Exif 処理があるため、事前準備が必要になる。

まず画像の方だが、「PHP で Windows用週間天気予報を作る」で紹介したとおり、WinBinderFreeImage をコールする。ダウンロードサイトからバージョン 3.17.0 をダウンロードし、"freeimage.dll" を ext ディレクトリに配置する。
さらに、bamcompile を使って "freeimage.dll" を EXE ファイルに埋め込んでおき、初回実行時にローカルドライブに展開するためのユーザー関数 initialize を用意した。

次に Exif 処理だが、"php_exif" が必要になる。
PHP バージョン 4 の extension から "php_exif" をコピー、"printexifwin.phpw]" と同じディレクトリに配置する。bamcompile のプロジェクトファイル "printexifwin.bcp" にも "EXTENSION printexifwin\php_exif.dll" を加えるのを忘れないようにしよう。

プログラムの解説:コモンダイアログ

0220: /**
0221:  * イベントハンドラ:メインウィンドウ
0222:  * @param int $window ウィンドウID
0223:  * @param int $id     イベントID
0224:  * @param int $ctrl   コントロール
0225:  * @param int $param  パラメータ
0226: */
0227: function process_main($window$id$ctrl=0, $param=0) { 
0228:     global $Items;
0229: 
0230:     switch($id) {
0231:         //検索
0232:         case IDC_FILE_BUTTON:
0233:             $fname = wb_sys_dlg_open($window, 'ファイル選択', '*.jpg');
0234:             putItems($window$fname);
0235:             break;
0236:         //詳細情報
0237:         case IDC_EXIF_LISTVIEW:
0238:             $arr = wb_get_selected(wb_get_control($windowIDC_EXIF_LISTVIEW));
0239:             $i = $arr[0];
0240:             $arr = wb_get_text(wb_get_control($windowIDC_EXIF_LISTVIEW), $i);
0241:             $str = "{$arr[0]}:{$arr[1]}";
0242:             wb_set_text(wb_get_control($windowIDC_EXIF_EDIT), $str);
0243:             break;
0244:         //ヘルプ
0245:         case IDC_HELP:
0246:             create_help($window, 'process_help');
0247:             break;  
0248:         //プログラム終了
0249:         case IDCLOSE:
0250:             wb_destroy_window($window);      //ウィンドウを破棄 
0251:             break;  
0252:     }
0253: }

ファイルを選択するコモンダイアログは WinBinder関数 wb_sys_dlg_open として用意されている。第2 引数はダイアログのタイトル、第3 引数はフィルターである。ここでは拡張子 .jpg のみを選択できるようにしている。戻値はパス名を含む完全ファイル名だ。

プログラムの解説:Exif情報の取得

0083: /**
0084:  * Exif情報を配列に格納する
0085:  * @param string $fname 画像ファイル名
0086:  * @param array  $exif  Exif情報を格納する配列
0087:  * @return int 1以上:Exif情報項目数
0088:  *               (-1): ファイルが存在しない
0089:  *               (-2): JPEG/TIFF以外の形式
0090:  *               (-3): Exif情報がない
0091: */
0092: function getexif($fname, &$exif) {
0093:     //ファイルの存在チェック
0094:     if (fopen($fname, 'rb') == FALSE)    return (-1);
0095: 
0096:     //JPEG/TIFFの型チェック
0097:     switch (exif_imagetype($fname)) {
0098:         case IMAGETYPE_JPEG:
0099:         case IMAGETYPE_TIFF_II:
0100:         case IMAGETYPE_TIFF_MM:
0101:             break;
0102:         default:
0103:             return (-2);
0104:     }
0105: 
0106:     //Exif情報を配列へ
0107:     if (($cls = @exif_read_data($fname)) == FALSE)   return (-3);
0108:     $cnt = 0;
0109:     foreach ($cls as $key=>$sect) {
0110:         if (is_array($sect) == FALSE) {
0111:             $exif[$cnt][0] = $key;
0112:             $exif[$cnt][1] = $sect;
0113:             $cnt++;
0114:         } else {
0115:             foreach($sect as $name=>$val) {
0116:                 $exif[$cnt][0] = $key . '.' . $name;
0117:                 $exif[$cnt][1] = $val;
0118:                 $cnt++;
0119:             }
0120:         }
0121:     }
0122: 
0123:     return $cnt;
0124: }

Exif 情報を配列に格納するユーザー関数 getexif は、「PHP で Exif 情報を表示する」で作ったものとほぼ同じである。ListView に格納する関係上、配列への格納方式を変更している。

プログラムの解説:Exif情報と画像の表示

0126: /**
0127:  * Exif情報一覧
0128:  * @param int $window ウィンドウID
0129:  * @param string $fname 画像ファイル名
0130:  * @return bool TRUE/FALSE;
0131: */
0132: function putItems($window$fname) {
0133:     clear_error($window);
0134:     wb_delete_items(wb_get_control($windowIDC_EXIF_LISTVIEW));
0135: 
0136:     $exif = array();
0137:     $res = getexif($fname$exif);
0138:     if ($res < 0) {
0139:         switch ($res) {
0140:             case (-1) :
0141:                 put_error($windowERROR_NOTFILEFOUND);
0142:                 break;
0143:             case (-2) :
0144:                 put_error($windowERROR_IRREGULARFORMAT);
0145:                 break;
0146:             case (-3) :
0147:                 put_error($windowERROR_NOTEXIF);
0148:                 break;
0149:         }
0150:         return FALSE;
0151:     }
0152: 
0153:     //Exif情報表示
0154:     wb_create_items(wb_get_control($windowIDC_EXIF_LISTVIEW), $exif);
0155: 
0156:     //画像表示
0157:     list($w0$h0) = wb_get_size(wb_get_control($window, IDC_FILE_IMAGE));
0158:     $dib = FreeImage_Load(FIF_JPEG$fname);
0159:     $width  = FreeImage_GetWidth($dib);
0160:     $height = FreeImage_GetHeight($dib);
0161:     if ($width > $w0) {
0162:         $cnv = $w0 / $width;
0163:         if (($h0 / $height) < $cnv) {
0164:             $cnv = $h0 / $height;
0165:         }
0166:     } else if ($height > $h0) {
0167:         $cnv = $h0 / $height;
0168:         if (($w0 / $width) < $cnv) {
0169:             $cnv = $w0 / $width;
0170:         }
0171:     } else {
0172:         $cnv = 1;
0173:     }
0174:     $dib = FreeImage_Rescale($dib$width * $cnv$height * $cnv);
0175:     $bmp = wb_create_image($width * $cnv$height * $cnv, FreeImage_GetInfoHeader($dib), FreeImage_GetBits($dib));
0176:     wb_set_image(wb_get_control($window, IDC_FILE_IMAGE), $bmp);
0177:     FreeImage_Unload($dib);
0178: }

配列に格納された Exif 情報は、「PHP で Windows用国立国会図書館検索プログラムをつくる」で紹介した ListView に表示する。

読み込んだ画像ファイルもサムネイル表示する。
オリジナルの画像は表示エリアより大きいことが予想されるので、WinBinder関数 FreeImage_Rescale を利用して画像のリサイズを行う。

コンパイル

コマンドラインから "bamcompile printexifwin.bcp" を実行する。コンパイルが完了すると、"printexifwin.exe" が生成される。"printexifwin.exe" は、DLL 不要で、単独で動作する EXE プログラムである。

参考サイト

(この項おわり)
header