実例で学ぶPHP拡張モジュールの作り方

第4回 WEBカメラから画像をキャプチャ(その2)

この記事を読むのに必要な時間:およそ 6 分

今回は前回製作したcvcaptureモジュールを改良し,リソースを使った継続的なキャプチャを実装します。

追加する機能は,CvCapture構造体を保持するリソースcvcaptureを定義し,カメラからcvcaptureリソースを作成する関数cv_create_camera_capture(),ファイルからcvcaprureリソースを作成する関数cv_create_file_capture(),フレームを取得し,静止画として保存する関数cv_save_capture()です。

specファイルを記述する

前回のspecファイルをベースに,リソース定義と新しい関数の定義を追加します。

リソースを定義する

まずはリソースです。リソースは<resources>タグ内の<resource>タグで記述します。<resoure>タグではname属性でリソース名,payload属性でリソースに保持する型を,allocで保持する値(payload属性で指定した型のポインタ)がZend APIのメモリを確保する関数emalloc()で確保された領域のアドレスかどうかを指定します。

また,<resource>タグ内の<destruct>タグでリソースに保持されている値を破棄する処理を記述します。ここで使っているresoureはCodeGen_PECLによって自動で定義される変数で,型はpayload属性で指定した型のポインタ(この場合はCvCapture *”)です。

リスト1 リソース定義(cvcapture-0.2.0.xml)

<resources>
  <resource name="cvcapture" payload="CvCapture" alloc="no">
    <description><?data
Storage for CvCapture.
    ?></description>
    <destruct><?data
cvReleaseCapture(&resource);
    ?></destruct>
  </resource>
</resources>

関数を定義する

次に,関数を定義します。今回作成する関数は,前回作成した関数をリソースを作成する関数と静止画を保存する関数に分割したものとなります。

図1 前回作成した関数との関係

図1 前回作成した関数との関係

リソースを作成する関数cv_create_camera_capture()とcv_create_file_capture()は,それぞれカメラを指定する数値,動画ファイルのパスを引数とします。リソースを返す関数は戻り値の型をresource リソースの種類と指定します。今回はcvcaptureリソースを返すので,resource cvcaptureです。テストでは戻り値がcvcaptureリソースかどうかを調べています。

リスト2 関数定義1(cvcapture-0.2.0.xml)

<function name="cv_create_camera_capture">
  <proto>resource cvcapture cv_create_camera_capture([int index])</proto>
  <summary>Start capturing frames from camera.</summary>
  <description>(省略)</description>
   <test>
    <code><?data
var_dump(cv_create_camera_capture());
    ?></code>
    <result mode="format"><?data
resource(%d) of type (cvcapture)
    ?></result>
  </test>
</function>

<function name="cv_create_file_capture">
  <proto>resource cvcapture cv_create_file_capture(string filename)</proto>
  <summary>Start capturing frames from video file.</summary>
  <description>(省略)</description>
  <test>
    <skipif><?data
if (!file_exists("sample.3g2")) {
  die("skip sample video file does not exist");
}
    ?></skipif>
    <code><?data
var_dump(cv_create_file_capture("sample.3g2"));
  ?></code>
  <result mode="format"><?data
resource(%d) of type (cvcapture)
    ?></result>
  </test>
</function>

cv_save_capture()は作成したcvcaptureリソースを第1引数とし,第2引数で保存先のパス,第3引数が指定されていればキャプチャした画像の高さのペアの配列を代入します。戻り値はキャプチャに成功すればtrue,失敗した場合はfalseです。

リスト3 関数定義2(cvcapture-0.2.0.xml)

<function name="cv_save_capture">
 <proto>bool cv_save_capture(resource cvcapture capture, string filename[, array &amp;size])</proto>
  <summary>Capture a frame.</summary>
  <description>(省略)</description>
   <test>
	  <code><?data
$capture = cv_create_camera_capture();
if ($capture && cv_save_capture($capture, "test_save.jpg", $size)) {
    print_r($size);
}
    ?></code>
    <result mode="format"><?data
Array
(
  [0] => %d
  [1] => %d
)
    ?></result>
  </test>
</function>

ソースコードを生成する

ここまでできたら,前回同様にpecl-genコマンドでモジュールのソースコードを生成します。

操作1 pecl-genを実行

$ pecl-gen --dir=cvcapture-0.2.0 cvcapture-0.2.0.xml
Creating 'cvcapture' extension in './cvcapture-0.2.0'

Your extension has been created in directory ./cvcapture.
See ./cvcapture-0.2.0/README and/or ./cvcapture-0.2.0/INSTALL for further instructions.

著者プロフィール

関山隆介(せきやまりゅうすけ)

ジンガジャパン株式会社に所属。PHP拡張モジュールを作った数なら(たぶん)日本一。PHP 5.3に対応したものはPEARチャンネルGitHubで公開中。

URLhttp://d.hatena.ne.jp/rsky/

コメント

コメントの記入