1. PHPでExifを操作する

デジタルカメラで撮影した写真から撮影情報を取得したい場合、みなさんはどのようにして行いますか。PHPのExif拡張モジュールを用いてExif関数を使用するというのが一般的かもしれませんが、今回はPHPのみで実装されたExif情報を操作するライブラリ「PEL」を紹介します。

PELはExif情報を操作するライブラリでPHPのみで実装されていて、PHP5の環境で使用することができます。また、Exif情報の読み込みはもちろんのこと追加変更をすることも可能です。

では早速使ってみることにしましょう。このライブラリは以下のURLからダウンロードすることができます。
http://pel.sourceforge.net/

デジタルカメラで撮影した写真を用意し、下記スクリプトのファイル名部分を変更して実行してください。

<?php
require_once('pel-0.9.1/PelJpeg.php');

$file "ファイル名";
$jpeg = new PelJpeg($file);
$app1 $jpeg->getExif();

if (
$app1) {
  
$tiff $app1->getTiff();
  
$ifd0 $tiff->getIfd();

  if (
$ifd0) {
    
$exif $ifd0->getSubIfd(PelIfd::EXIF);
    
$data['exif_version']       =
$exif->getEntry(PelTag::EXIF_VERSION)->getText(); // Exifバージョン
    
$data['pixel_x']            =
$exif->getEntry(PelTag::PIXEL_X_DIMENSION)->getValue(); // 幅
    
$data['pixel_x']            =
$exif->getEntry(PelTag::PIXEL_X_DIMENSION)->getValue(); // 幅
    
$data['pixel_y']            =
$exif->getEntry(PelTag::PIXEL_Y_DIMENSION)->getValue(); // 高
    
$data['date_time_original'] =
$exif->getEntry(PelTag::DATE_TIME_ORIGINAL)->getText(); // オリジナルの作成日時
    
$data['make']               =
$ifd0->getEntry(PelTag::MAKE)->getText(); // メーカー
    
$data['model']              =
$ifd0->getEntry(PelTag::MODEL)->getText(); // モデル
    
$data['fnumber']            =
$exif->getEntry(PelTag::FNUMBER)->getValue(); // 絞り値
    
$data['exposure_time']      =
$exif->getEntry(PelTag::EXPOSURE_TIME)->getValue(); // 露出時間
    
$data['iso_speed_ratings']  =
$exif->getEntry(PelTag::ISO_SPEED_RATINGS)->getValue(); // ISO速度
    
$data['exposure_bias']      =
$exif->getEntry(PelTag::EXPOSURE_BIAS_VALUE)->getValue(); // 露出補正
    
$data['focal_length']       =
$exif->getEntry(PelTag::FOCAL_LENGTH)->getValue(); // 焦点距離
  
}

  
var_dump($data);

}

その写真ファイルにExif情報が埋め込まれている場合、そのバージョンや撮影日時、カメラのメーカーや機種、絞り値、焦点距離等々が表示されると思います。

また、先の紹介でもふれましたがこのライブラリはExif情報を追加変更することも可能です。

<?php
require_once('pel-0.9.1/PelJpeg.php');

$filename "DSC_3297.JPG";
$jpeg = new PelJpeg($filename);
$app1 $jpeg->getExif();

if (
$app1) {
  
$tiff $app1->getTiff();
  
$ifd0 $tiff->getIfd();

  if (
$ifd0) {
    
$exif $ifd0->getSubIfd(PelIfd::EXIF);
    
$text "コメントです";
    
$entry $exif->getEntry(PelTag::USER_COMMENT);
    if (!
$entry) {
      
$entry = new PelEntryUserComment(mb_convert_encoding($text"JIS",
"auto"), "JIS");
      
$exif->addEntry($entry);
    } else {
      
$entry->setValue(mb_convert_encoding($text"JIS""auto"), "JIS");
    }
    
file_put_contents($filename$jpeg->getBytes());
  }
}

上記サンプルスクリプトでは「UserComment」タグを追加しコメントを追加しています。写真ファイルに変更したいExifタグが存在しない場合はaddEntryメソッドで追加し、すでに存在している場合はsetValueメソッドで値を変更しています。

Exif情報の表示と追加変更を簡単に紹介しました。サポートしているExifタグ等はPELのサイトを参照してください。PHPに用意されているExif関数より高機能なPEL、興味のある方は使ってみてはいかがでしょうか。

2. コマンドラインで対話的なユーザーインターフェースを作ろう

以前のTipsで対話形式のコマンドラインプログラムについてご紹介しましたが、そのまま文字を表示するだけではなく、もっと画面全体を使って処理を行わせたいと思ったことはないでしょうか?

Ncurses端末画面制御関数を使えば、そのような画面全体を使ったユーザーインターフェースを作ることができます。

RHELやCentOSなどのディストリビューションであれば、php-ncursesパッケージが用意されていますので、yumなどを使用してインストールするだけで使用できます。ご自身でPHPをコンパイルしてインストールされている方は、PHPのconfigure時に「--with-ncurses[=DIR]」を指定してください。

なお、この拡張モジュールは実験的なものであるため、自己責任で使用してください。 また、Microsoft Windows環境で実行するには、Cygwinの実行環境が必要となります。

では、以下がサンプルプログラムになります。
カーソルキーの上下でメニューが移動し、Exitを選択してエンターキーを押下すると、プログラムが終了します。

#!/usr/bin/env php
<?php
// ncursesの初期化
ncurses_init();

// 画面サイズの取得
ncurses_getmaxyx(STDSCR$height$width);
// 枠の描画
ncurses_border(0x7c0x7c0x2d0x2d0x2b0x2b0x2b0x2b);
// 文字列の表示
ncurses_mvaddstr(02"[ Ncurses Sample ]");
// カーソルの消去
ncurses_curs_set(false);
// 画面のリフレッシュ
ncurses_refresh();

$menu array(
    
"Menu Item 1",
    
"Menu Item 2",
    
"Menu Item 3",
    
"Exit"
);
$menu_count count($menu);
$pos 0;
$loop true;

// ウィンドウの作成
$window ncurses_newwin($menu_count+220, ($height-$menu_count)/2, ($width-20)/2);
// ウィンドウ枠の描画
ncurses_wborder($window0x7c0x7c0x2d0x2d0x2b0x2b0x2b0x2b);

while (
$loop) {
    
// メニューの表示
    
for ($i 0$i $menu_count$i++) {
        if(
$i == $pos){
            
// 反転表示をON
            
ncurses_wattron($windowNCURSES_A_REVERSE);
            
ncurses_mvwaddstr($window$i+11$menu[$i]);
            
// 反転表示をOFF
            
ncurses_wattroff($windowNCURSES_A_REVERSE);
        }else{
            
ncurses_mvwaddstr($window$i+11$menu[$i]);
        }
    }
    
// ウィンドウのリフレッシュ
    
ncurses_wrefresh($window);
    
// キーボード入力の判定
    
$key ncurses_getch($window);
    switch (
$key) {
    case 
NCURSES_KEY_UP:
        
$pos--;
        if (
$pos 0) {
            
$pos 0;
        }
        break;
    case 
NCURSES_KEY_DOWN:
        
$pos++;
        if (
$pos >= $menu_count) {
            
$pos $menu_count 1;
        }
        break;
    case 
13// KEY_ENTER
        
if ($menu[$pos] == "Exit") {
            
$loop false;
        }
        break;
    }
}

// ncursesの終了
ncurses_end();
?>

また、Ncurses関数と同様に画面全体を使ったインターフェースを作成できるものとして、Newtという拡張モジュールがあります。

こちらはチェックボックスやラジオボタンなどを手軽に作成することができます。興味のある方はPHPのマニュアルにサンプルソースも記載されていますので、ぜひご覧ください。

文字だけでは味気ないなと感じたときなど、これらの関数を使ってアプリケーションを作成してみては如何でしょうか。

バックナンバーについて

TIPS-MLは、毎週金曜日に更新され、新しい記事が掲載されます。