EDSDKでキャノンのカメラをPCから制御する

その1 まずはEDSDKの入手と最初のプログラム

通称はEDSDKですが、正しくは”デジタルカメラ開発支援パッケージ” SDK Camera API Packageの一部です。EDSDK Canonとかのキーワードで検索すればすぐに見つかりますが、

ここへ行きます。

うーんと下の方へ行き、

ここのダウンロードをクリック。

申し込みで必要なものを選択して、”次へ”

面倒でも”必須”項目には記入。ちなみに個人レベルでも申し込めます。

お疲れ様。この手順が面倒ならば、拙作のVectorにアップしてある”Camera Remote Control 64″をダウンロードしてもedsdk.dllは入手できます。ただし最新のバージョンではありません。最新版でないと嫌だという方は、上記手順で、登録メールアドレスにダウンロードリンクが送られてきますから、そこからダウンロード。基本的にはCanonさんが新しいカメラをリリースすると、新しいEDSDKが出ることが多いです。そのバージョンとサポートしているカメラの関係は、

latest EDSDK

とかのキーワードの検索で見つかる、

へ行くと判明します。

上記は、2025/7/17時点の状況ですが、最新版のedsdkのバージョンは、V13.19.10で、新しいカメラとしては、EOS R50Vまでサポートしているということが分かります。もの凄く古いカメラでもサポートしています。下位互換性も高いです。このテーブルに掲載されていなくても、使える可能性は高いですが、前記事で扱った初代のEOS Kiss Digital Nとかは、Windowsのサポートが終わっているので、edsdkからは制御できません。原則として、カメラをPCにUSBで接続して、認識されて、内部ストレージが見える状態にならないと、EDSDK経由ではコントロールできません。さてダウンロードした、

下の方のzipを解凍しましょう。解凍したフォルダーに入って、

ちなみに、Windows 11時代なので、64bit版のみを扱いますね。上図のように何もないところで右クリック->Open Git Bash hereを選択。

上記のように“mkexp”を起動します。32bit版の場合は“implib”です。これでedsdk.dllをC++ Builder CEから使う準備はほぼできました。簡単というか初歩的なプログラムを作成してみましょう。コマンドラインプログラムです。

ceedsdk.aができています。いかにも静的リンクライブラリに見えますが、エントリーポイントのみで実体はあくまでedsdk.dllですから、実行時にedsdk.dllが要ります。

main.cppは、

#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");

//	return err;
}

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);
}

int	main()
{
//	char	buff[100];
	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 = EdsSetObjectEventHandler(camera,kEdsObjectEvent_All,handleObjectEvent,NULL);
	err = EdsOpenSession(camera);

	err = EdsSetObjectEventHandler(camera,kEdsObjectEvent_All,handleObjectEvent,NULL);
	if( err != EDS_ERR_OK) {
		printf("can't hookup handle routine\n");
	}

	//err = EdsSetCameraStateEventHandler(camera, kEdsStateEvent_All, handleStateEvent, NULL); 
	//if( err != EDS_ERR_OK) {
	//	printf("can't hookup state handle routine\n");
	//}

/*

err = EdsSendStatusCommand( camera, kEdsCameraStatusCommand_UILock, 0);
if(err == EDS_ERR_OK)
{
	printf("camera locked\n");
}
else {
	printf("lock failed code is %x\n",err);
}




	err =EdsSetPropertyData(camera,kEdsPropID_ImageQuality,0,sizeof(imgQ),&imgQ);
	if( err != EDS_ERR_OK) {
		printf("can't setup image quality  to jpeg only large error code is %x\n",err);
		
	}

*/
	//err =EdsSetPropertyData(camera,kEdsPropID_SaveTo,0,4,&saveTarget);
	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

	//EdsOpenSession(camera);
	EdsUInt32 record_start = 4; //     B e ̊J n
	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; //     B e ̏I  
	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);
	//Sleep(1000);
	


	


	printf("done and terminate EDSDK\n");
	//gets(NULL);
	EdsTerminateSDK();

}

このプラグラムがやっていることを箇条書きすると、

  • EDSDKの使用準備 EdsInitializeSDK()
  • カメラリストの取得 EdsGetCameraList(&cameraList)
  • カメラの選択 EdsOpenSession(camera)
  • イベントハンドラーの登録 EdsSetObjectEventHandler(camera,kEdsObjectEvent_All,handleObjectEvent,NULL)
  • パラメーターセット EdsSetPropertyData(camera, kEdsPropID_SaveTo, 0, sizeof(saveTo), &saveTo) 等など
  • ライブビューにセット start_liveview(camera)
  • 動画撮影スタート  EdsSetPropertyData(camera, kEdsPropID_Record, 0, sizeof(record_start), &record_start)
  • 時間稼ぎ Sleep(7000+1000)
  • 動画撮影ストップ EdsSetPropertyData(camera, kEdsPropID_Record, 0, sizeof(record_stop), &record_stop)
  • イベントループ ここでダウンロードがfireします
  • ライブビュー解除 stop_liveview(camera)
  • EDSDK終了 EdsTerminateSDK()

となります。内容的には、5秒間の動画撮影を行い、録画ファイルをダウンロードしておしまい。という単純なものですが、ステップはこれだけ必要です。Edsなんとかかんとかの嵐ですから、このまま使用するのはなかなかしんどいですね。

具体的にBuild and Runしてみましょうか?IDEを立ち上げて、

新規作成から”コンソールアプリケーション C++ Builder”を選択します。

“OK”でおけ。

一旦プロジェクトを適切なフォルダー名下でセーブし、そのディレクトリへ、ヘッダーや先に作ったceedsdk.a等やmain.cppを追加して、

IDEのプロジェクトエクスプローラーでも、ファイル等を追加して、

となっていればおけです。ターゲットプラットフォームを64ビットにするのを忘れずに。

プロジェクト1をBuild SHIFT-F9でエラーが出なければ、Win64/Debugフォルダーにedsdk.dllを移します。で、RUN。面倒なので”Bash”から、

MOVが転送されています。

メディアプレイヤーなどで再生すれば、

めでたし、めでたし。

ですが、もっと複雑なプログラムをこの流儀で作るのはかなり”頭が痛い”ので、楽をすることを考えましょう。せっかくのC++ですからクラスを作って、抽象化ないしゴチャゴチャを隠蔽することを行うのでした。ついでにCanonのみならず、Nikonのカメラもサポートしてしまおうという大胆なプロジェクトがある程度まで完成しています。というのは次号以降で。

コメント