GW前に書いたこの記事の続編です。
http://ameblo.jp/delphinus1024/entry-12018016756.html
念のため重複になりますが、gphoto2とは多くの民生カメラをUSB制御できるオープンソースのLinux(Mac)ソフトウェアで、libgphoto2というのはその心臓部を司るライブラリ。
うまく使いこなせればカメラの自動制御などが可能になって表現の幅が広がる(かも)。
gphoto2でもかなりのことができるのですが、それでも機能的・パフォーマンス的に不足な場合はgphoto2を介さずにlibghoto2を直接制御することになります。
それが今回のテーマです。
カメラマンでここまで必要とする人はいないのか、Web上にまとまったわかりやすい情報がほとんどありません。
断片的な情報を寄せ集めてなんとか使えるところまで来ましたので、個人的な備忘録を兼ねて。
以下参考にされる方は自己責任・No Question・No Supportでお願いします。
ここでは前回の記事と同じこと(マニュアル露光にしてブラケット3枚を20秒毎に3回繰り返す)をC++のプログラムからlibgphoto2を直接叩いて実行してみます。
以下ビルドするには前回書いた環境構築が正常に行われている必要があり、gccが使用できる環境である必要があります。
プログラムの内容はかなりボリュームがありますが、とりあえず動作することを目的にしたので、最適化していないため冗長な箇所やデバッグ時のゴミも多いです。Webの情報をかき集めて作ったので、コーディングスタイルも各所まちまちなのもご了承ください。
C++のテンプレートなどを使えば半分以下の分量になるかもしれませんが、サンプルなのでそのままにしています。
仕様変更の多いライブラリなので、将来のバージョンでは動作しなくなる可能性もあるかと思います。カメラの種類によっても挙動が異なるかも知れず、あくまでも参考程度だと思ってください。
下の環境で動作確認しています。
・gphoto2 2.5.6
・libgphoto2 2.5.7
・libgphoto2_port 0.12.0
・5D2 & 5D3
・VMWare+Ubuntu13.04(少々古いが…)
ダウンロードは
https://github.com/delphinus1024/gp_bracket
ビルド方法はreadmeに詳しく書いてあるが、コンソール上で
make
をすれば実行ファイルbracketが出来上がります。
実行方法はまず、EOSをUSB接続・電源ON
lsusbでEOSが見えていることを確認後、
./bracket
と入力。
正常動作すれば、EOSが3x3=合計9回シャッターを切った後にプログラム終了するはずです。
暗い場所などフォーカスが会わない時は動作破綻するので、マニュアルフォーカスに切り替えておいた方が問題が起こりにくい。
プログラムの大筋は処理の内容と照らし合わせればだいたい想像がつくかと思いますが、理解のキーとなる点をいくつか。
・gp_の接頭語がつく関数がlibghoto2が提供するAPI。
・Config Valuesの箇所で主要なパラメータの一覧を宣言してある(ISO,シャッタースピード,絞り…etc)。サンプルでは使用していないものもとりあえず入れてある。
set_xxx, get_xxx関数(xxxは設定対象名)でそれらの値の取得・変更を行う。ここでは5D2,5D3を想定していますが、カメラが変わったら宣言の変更が必要になるかも。
・set_xxx, get_xxx内部で"widget"とつくlibgphoto2関数を操作しているが、widget = 設定値(config value)名と考えてよいみたい。前回に書いたようにConfig ValueはTree状になっているためwidgetと呼んでいるみたい。
・main関数の最初でGPContextを取得しているが、このcontextというのがlibgphoto2の「総元締め」のような役割を果たすみたい。これ以降のlibgphoto2のAPIの多くはこのcontextを渡す必要がある。contextは(カメラが複数あっても)プログラム内で一個取得すれば十分。
・カメラは複数個接続/制御できる。このプログラム内ではすべての接続されたカメラをOpen(open_camera関数参照)して、以降の操作は最初のカメラのみに行っている。プログラム終了時にOpenしたカメラはExit(gp_camera_exit)する必要がある。プログラムを書き換えれば複数のカメラを平行して制御することも可能。
・portやabilitiesという名前のついた関数をOpen前に呼んでいるが、これらはとりあえずオマジナイと思っておいても支障はないみたい。
・プログラムでは撮影したデータはCFカードに残す設定にしているが(set_capture_target関数参照)、#define GET_FILEをアンコメントするとホスト側にも同じデータをUSB経由で取得するようになる。
・撮影を行うのがgp_camera_capture関数。この関数は撮影が終了してCFカードにデータが格納されるまで制御を返さない。複数のカメラをパラレルで撮影するときなどは撮影開始後に制御をすぐ返すcp_camera_trigger_captureを使用した方が便利かもしれない。(#define DO_TETHER_CAPTUREをアンコメントするとその部分が有効になる) この際、撮影終了を判断するにはカメラからGP_EVENT_FILE_ADDEDイベントが帰ってくるのを待つ必要がある。これに関してはcamera_tether関数内を参照。
・エラーや情報通知用のコールバック関数を設定するのが、gp_context_set_error_funcとgp_context_set_status_func。何か起こればコールバックが起こる。必要があれば処理する。
・その他、実践で流用できるようにLiveViewやFocus関連などサンプルで使用していない関数なども入れてあります。いろいろ実験してみるといろいろ発見があるかもしれません。