C++ Builder CE Cameralibの活用

1.CanonNikonから供給されている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の最小限のプログラムを示します。


 

コメント