專案需求:多台 Canon 單眼相機透過 USB 連接電腦,定時拍照並自動上傳。本文比較 Canon SDK 與 Windows Image Acquisition (WIA) 兩種介面,分享 WIA 列舉裝置、下載影像、SDK 事件處理的完整代碼。
| 維度 | Canon EOS SDK | WIA (Windows Image Acquisition) |
|---|---|---|
| 支援型號 | 僅 Canon 相容機種 | 所有符合 WIA 標準的影像裝置 (掃描儀、Webcam、相機) |
| 功能深度 | 完整控制:快門、光圈、ISO、對焦、Live View | 基礎操作:拍照、下載、屬性讀寫 |
| .NET 整合 | 官方提供 .NET Wrapper (EDSDK.dll) | 系統內建 COM 元件,直接加參考 |
| 取得裝置內檔案 | .NET 版 SDK **缺乏** 列舉/下載 API | 原生支援列舉裝置儲存區、下載檔案 |
| 適用場景 | 需精細控制相機參數的專業應用 | 通用影像採集、多品牌裝置、簡單拍照下載 |
專案最終採用 **WIA** 解決「多裝置自動下載」,輔以 SDK 處理「拍攝觸發與參數設定」。
using WIA; // 需加入 COM 參考 "Microsoft Windows Image Acquisition Library v2.0"
public class CameraManager
{
private readonly DeviceManager _deviceManager = new DeviceManagerClass();
public IEnumerable GetCameraDevices()
{
foreach (DeviceInfo info in _deviceManager.DeviceInfos)
{
if (info.Type == WiaDeviceType.CameraDeviceType)
yield return info;
}
}
public void DownloadAllImages(Action onFileDownloaded)
{
int index = 1;
foreach (var info in GetCameraDevices())
{
var device = info.Connect();
var param = new CameraParam { Device = device, DeviceId = info.DeviceID, Index = index++ };
// 非同步下載避免阻塞 UI
Task.Run(() => DownloadFromCamera(param, onFileDownloaded));
}
}
private void DownloadFromCamera(CameraParam param, Action callback)
{
try
{
// 遍歷儲存區項目
foreach (Item item in param.Device.Items)
{
if (item.IsFolder)
{
DownloadFromFolder(item, param, callback); // 遞迴處理資料夾
}
else
{
DownloadItem(item, param, callback);
}
}
}
catch (Exception ex)
{
// 記錄錯誤
}
}
private void DownloadFromFolder(Item folder, CameraParam param, Action callback)
{
foreach (Item item in folder.Items)
{
if (item.IsFolder) DownloadFromFolder(item, param, callback);
else DownloadItem(item, param, callback);
}
}
private void DownloadItem(Item item, CameraParam param, Action callback)
{
string tempPath = Path.Combine(Path.GetTempPath(), $"Cam{param.Index}_{item.Name}");
var transfer = (IWiaDataTransfer)item.Transfer(WIA.FormatID.wiaFormatJPEG, false);
transfer.GetData(out object data);
File.WriteAllBytes(tempPath, (byte[])data);
callback?.Invoke(param.DeviceId, tempPath);
}
}
public class CameraParam
{
public Device Device { get; set; }
public string DeviceId { get; set; }
public int Index { get; set; }
}
.NET 版 SDK 提供 5 種委託回呼:
public delegate uint EdsProgressCallback(uint percent, IntPtr context, ref bool cancel);
public delegate uint EdsCameraAddedHandler(IntPtr context);
public delegate uint EdsPropertyEventHandler(uint eventId, uint propertyId, uint param, IntPtr context);
public delegate uint EdsObjectEventHandler(uint eventId, IntPtr objectRef, IntPtr context);
public delegate uint EdsStateEventHandler(uint eventId, uint param, IntPtr context);
// 註冊事件
_camera.SetObjectEventHandler(EdsObjectEventHandler, IntPtr.Zero);
_camera.SetPropertyEventHandler(EdsPropertyEventHandler, IntPtr.Zero);
// 回呼實作
private uint OnObjectEvent(uint eventId, IntPtr objRef, IntPtr context)
{
if (eventId == EDSDK.ObjectEvent_DirItemCreated) // 新檔案建立
{
// 取得檔案資訊並下載
DownloadFile(objRef);
}
return EDSDK.EDS_ERR_OK;
}
USB 介面類別碼 (`bInterfaceClass`) 決定裝置在系統中的呈現:
若 `DriveInfo` 看不到相機,請嘗試 WIA `DeviceManager` 列舉 `CameraDeviceType`。
原始碼專案包含 WIA 封裝類、SDK 事件綁定、定時排程、上傳模組,歡迎參考擴充。