1.CanonやNikonから供給されているSDKをくるんで、簡便にUSB接続されたカメラを制御する
まずできあがったプログラムを見てみよう
拙作のUtilityのうちVectorにアップしたもので割とダウンロード数が多いものの一つが、Camera Remote Controlである。詳しくはダウンロードしていただいて、説明書をごらんになれば分かりますが、要はPCにUSB経由で接続されたCanonのEOSやNikonのカメラを制御するプログラムです。これは32bit版と64bit版がありますが、Nikonが32bit版のSDKの供給を止めているので、後者に限定するとそのダウンロードリンクは、https://www.vector.co.jp/download/file/winnt/hardware/fh769375.html
になります。一応32bit版も残してはあります。起動すると、

こんな感じで、メニューでパラメーターを設定し、ボタンを押すことで静止画を画面に表示し、ファイルにセーブし、ライブビューを見て、動画を保存することが可能です。一通りのことができます。これのソースをまるごとここで公開することを考えましたが、SDKで供給されているソースを修正して使っているので、それを公開することはためらわれますし、そもそも供給されているヘッダー群もいくら修正していないそのままで使うとしても、ソースに同梱した形で供給することは問題になるかもしれません。ので、公開できる範囲でライブラリとして公開して、サンプルとしては、ミニマムなプログラムのソースを提示することを考えました。で、今回はその第1弾です。まず拙作のラッパー(wrapper)を使わない素のEDSDKプログラミングはどうなるかを提示します。
#include <stdio.h>
#include <Windows.h>
#include "EDSDK.h"
#include "EDSDKErrors.h"
#include "EDSDKTypes.h"
int filecount=1; // Jpeg large fine only
int transfered = 0;
EdsCapacity newcapacity = {0x7FFFFFFF,0x1000,1};
void downloadImage(EdsDirectoryItemRef directoryItem)
{
EdsError err = EDS_ERR_OK;
EdsStreamRef stream = NULL;
// Get directory item information
EdsDirectoryItemInfo dirItemInfo;
err = EdsGetDirectoryItemInfo(directoryItem, & dirItemInfo);
// Create file stream for transfer destination
if(err == EDS_ERR_OK){
err = EdsCreateFileStream( dirItemInfo.szFileName,
kEdsFileCreateDisposition_CreateAlways,
kEdsAccess_ReadWrite, &stream);
}
// Download image
if(err == EDS_ERR_OK){
err = EdsDownload( directoryItem, dirItemInfo.size, stream);
}
// Issue notification that download is complete
if(err == EDS_ERR_OK){
err = EdsDownloadComplete(directoryItem);
filecount--;
if(filecount == 0 )
transfered = 1;
}
// Release stream
if( stream != NULL){
EdsRelease(stream);
stream = NULL;
}
err = EdsDeleteDirectoryItem(directoryItem);
if (err == EDS_ERR_OK)
printf("file in camera deleted\n");
}
EdsError EDSCALLBACK handleObjectEvent( EdsObjectEvent event,
EdsBaseRef object,
EdsVoid * context)
{
// do something
// printf("callbacked...\n\n\n");
switch(event){
case kEdsObjectEvent_DirItemCreated:
printf("dir item request diritemcreated raised......\n\n");
downloadImage(object);
break;
default:
break;
}
// Object must be released
if(object){
EdsRelease(object);
}
return EDS_ERR_OK;
}
void start_liveview(EdsCameraRef camera)
{
EdsOpenSession(camera);
EdsUInt32 device = kEdsPropID_Evf_OutputDevice;
EdsGetPropertyData(camera, kEdsPropID_Evf_OutputDevice, 0, sizeof(device), &device);
device |= kEdsEvfOutputDevice_TFT;
EdsSetPropertyData(camera, kEdsPropID_Evf_OutputDevice, 0, sizeof(device), &device);
}
void stop_liveview(EdsCameraRef camera)
{
EdsUInt32 device;
EdsGetPropertyData(camera, kEdsPropID_Evf_OutputDevice, 0, sizeof(device), &device);
device &= ~kEdsEvfOutputDevice_TFT;
EdsSetPropertyData(camera, kEdsPropID_Evf_OutputDevice, 0, sizeof(device), &device);
EdsCloseSession(camera);
}
main()
{
EdsError err = EDS_ERR_OK;
EdsCameraListRef cameraList = NULL;
EdsCameraRef camera = NULL;
EdsUInt32 count = 0;
int IsSDKLoaded = 0;
EdsDeviceInfo deviceInfo;
EdsInt32 saveTarget = kEdsSaveTo_Host;
MSG msg;
EdsUInt32 imgQ = EdsImageQuality_LJF;
err = EdsInitializeSDK();
if( err == EDS_ERR_OK )
IsSDKLoaded = 1;
else {
printf("can't init. EDSDK\n");
EdsTerminateSDK();
exit(1);
}
printf("Getting camera list...\n");
err = EdsGetCameraList(&cameraList);
if( err == EDS_ERR_OK ){
err = EdsGetChildCount(cameraList, &count);
if( count == 0 )
printf("no cameras...\n");
else
printf("camera count is %d\n",count);
}
else {
printf("can't get camera list...\n");
EdsTerminateSDK();
exit(1);
}
err = EdsGetChildAtIndex(cameraList,0,&camera);
err = EdsGetDeviceInfo(camera,&deviceInfo);
// now select camera
// set event handler before opensession is that ok?
err = EdsOpenSession(camera);
err = EdsSetObjectEventHandler(camera,kEdsObjectEvent_All,handleObjectEvent,NULL);
if( err != EDS_ERR_OK) {
printf("can't hookup handle routine\n");
}
err = EdsSetCapacity(camera,newcapacity);
if( err != EDS_ERR_OK) {
printf("can't setup host capacity\n");
}
EdsUInt32 saveTo = kEdsSaveTo_Camera;
err = EdsSetPropertyData(camera, kEdsPropID_SaveTo, 0, sizeof(saveTo), &saveTo);
if (err != EDS_ERR_OK) {
printf("can't setup saveto target to host\n");
}
start_liveview(camera);
Sleep(500); // will wait
EdsUInt32 record_start = 4;
err = EdsSetPropertyData(camera, kEdsPropID_Record, 0, sizeof(record_start), &record_start);
if (err != EDS_ERR_OK) {
printf("can't start movie recording\n");
}
else
printf("movie recording started\n");
Sleep(7000+1000); // wait 1 seconds
printf("will stop movie recording\n");
EdsUInt32 record_stop = 0;
err = EdsSetPropertyData(camera, kEdsPropID_Record, 0, sizeof(record_stop), &record_stop);
if (err != EDS_ERR_OK) {
printf("can't stop movie recording\n");
}
else
printf("movie recording stopped\n");
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
if (transfered)
break;
}
stop_liveview(camera);
printf("done and terminate EDSDK\n");
EdsTerminateSDK();
}
これはコマンドラインプログラムでそのままVisual CでBuildして実行可能です。Canonのカメラで動画撮影を7秒間行い、得られた動画ファイルをPC側に転送するだけですが、Edsなんとかかんとかの嵐です。慣れれば何をやっているかは分かるようになりますが、ある手続きのための一塊の手順がわかりにくいですよね。で、これをWrapperを使って書き換えると。
#include <stdio.h>
#include "cameralib.h"
Camera* camera;
extern int filecount=1;
int Live=0;
#define Duration 7
EdsError EDSCALLBACK ProgressFunc(EdsUInt32 inPercent, EdsVoid* inContext, EdsBool* outCancel)
{
return EDS_ERR_OK;
}
void UpdateProgressBar(unsigned long value)
{
}
int main()
{
camera = new Camera();
if( camera->TotalCameraCount > 0 ){
printf("%s found\n",camera->GetName());
}
else {
printf("no cameras found aborting....\n");
return 1;
}
camera->RecordMovie();
Sleep(1000*Duration);
camera->StopMovie();
delete camera;
return 0;
}
これだけですが、ちゃんと動きます。最低限のエラーチェックもしつつ、コアな部分は、
camera = new Camera(); でCameraのインスタンスを作成して、
それに対して、
camera->RecordMovie(); して、
Sleep(1000*Duration); 時間おいて
camera->StopMovie(); するというこれ以上簡単化できないレベルです。
しかも対応していれば、CanonのカメラでもNikonのカメラでもオッケーです。Cameralibの有用性はご理解いただけましたか?次の記事ではVCLの最小限のプログラムを示します。
コメント