使用edsdk 2.8拍照并直接将图像保存到PC
Posted
技术标签:
【中文标题】使用edsdk 2.8拍照并直接将图像保存到PC【英文标题】:take picture and directly save image to pc using edsdk 2.8 【发布时间】:2010-09-21 16:46:56 【问题描述】:我是 EDSDK 2.8 的新手
目前,我的程序可以拍照。但是,当拍摄照片时,该照片会临时存储在佳能相机的缓冲区中。我想知道如何将它的目录保存到PC?
有人有什么想法吗?或者 c# 或 vb.net 中的示例代码?
【问题讨论】:
【参考方案1】:我也是这样做的,因为我的相机中没有存储卡,并且想在发送拍照命令后将图像传输到主机。这是我在佳能 EOS50D 中未安装存储卡时调用 ObjectEventHandler
回调的方法。
EdsUInt32 setsaveto = kEdsSaveTo_Both;
err = EdsSetPropertyData(camera, kEdsPropID_SaveTo, 0, sizeof(setsaveto), &setsaveto);
瞧,回调被调用,然后我可以继续执行 Wayne 在之前的帖子中发布的 getCapturedItem()
函数。
【讨论】:
【参考方案2】:这是我所做的:
首先,您必须在创建对象(即图片)时注册回调事件。我在我创建的 registerEvents 方法中做到了这一点:
// Register OBJECT events
edsObjectEventHandler = new EDSDK.EdsObjectEventHandler(objectEventHandler);
error = EDSDK.EdsSetObjectEventHandler(this.CameraDevice,
EDSDK.ObjectEvent_All, edsObjectEventHandler, IntPtr.Zero);
if (EDSDK.EDS_ERR_OK != error)
throw new CameraEventRegistrationException("Unable to
register object events with the camera!", error);
objectEventHandler
是创建图片时将调用的方法。
该方法需要符合 API 规定的接口。这是该方法的示例实现:
/// <summary>
/// Registered callback function for recieving object events
/// </summary>
/// <param name="inEvent">Indicate the event type supplemented.</param>
/// <param name="inRef">Returns a reference to objects created by the event.</param>
/// <param name="inContext">Passes inContext without modification</param>
/// <returns>Status 0 (OK)</returns>
private uint objectEventHandler(uint inEvent, IntPtr inRef, IntPtr inContext)
switch (inEvent)
case EDSDK.ObjectEvent_DirItemCreated:
this.invokeNewItemCreatedEvent(new NewItemCreatedEventArgs(getCapturedItem(inRef)));
Console.WriteLine("Directory Item Created");
break;
case EDSDK.ObjectEvent_DirItemRequestTransfer:
Console.WriteLine("Directory Item Requested Transfer");
break;
default:
Console.WriteLine(String.Format("ObjectEventHandler: event 0, ref 1", inEvent.ToString("X"), inRef.ToString()));
break;
return 0x0;
在此示例中,我转身并生成我自己的事件,该事件具有对流对象的引用。这是由以下代码处理的:
/// <summary>
/// Gets a photo or video clip from the camera
/// </summary>
/// <param name="directoryItem">Reference to the item that the camera captured.</param>
/// <returns></returns>
private CapturedItem getCapturedItem(IntPtr directoryItem)
uint err = EDSDK.EDS_ERR_OK;
IntPtr stream = IntPtr.Zero;
EDSDK.EdsDirectoryItemInfo dirItemInfo;
err = EDSDK.EdsGetDirectoryItemInfo(directoryItem, out dirItemInfo);
if (err != EDSDK.EDS_ERR_OK)
throw new CameraException("Unable to get captured item info!", err);
// Fill the stream with the resulting image
if (err == EDSDK.EDS_ERR_OK)
err = EDSDK.EdsCreateMemoryStream((uint)dirItemInfo.Size, out stream);
// Copy the stream to a byte[] and
if (err == EDSDK.EDS_ERR_OK)
err = EDSDK.EdsDownload(directoryItem, (uint)dirItemInfo.Size, stream);
// Create the returned item
CapturedItem item = new CapturedItem();
if (err == EDSDK.EDS_ERR_OK)
IntPtr imageRef = IntPtr.Zero;
err = EDSDK.EdsCreateImageRef(stream, out imageRef);
if (err == EDSDK.EDS_ERR_OK)
EDSDK.EdsImageInfo info;
err = EDSDK.EdsGetImageInfo(imageRef, EDSDK.EdsImageSource.FullView, out info);
if (err == EDSDK.EDS_ERR_OK)
item.Dimensions = new com.waynehartman.util.graphics.Dimension((int)info.Width, (int)info.Height);
EDSDK.EdsRelease(imageRef);
if (err == EDSDK.EDS_ERR_OK)
byte[] buffer = new byte[(int)dirItemInfo.Size];
GCHandle gcHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
IntPtr address = gcHandle.AddrOfPinnedObject();
IntPtr streamPtr = IntPtr.Zero;
err = EDSDK.EdsGetPointer(stream, out streamPtr);
if (err != EDSDK.EDS_ERR_OK)
throw new CameraDownloadException("Unable to get resultant image.", err);
try
Marshal.Copy(streamPtr, buffer, 0, (int)dirItemInfo.Size);
item.Image = buffer;
item.Name = dirItemInfo.szFileName;
item.Size = (long)dirItemInfo.Size;
item.IsFolder = Convert.ToBoolean(dirItemInfo.isFolder);
return item;
catch (AccessViolationException ave)
throw new CameraDownloadException("Error copying unmanaged stream to managed byte[].", ave);
finally
gcHandle.Free();
EDSDK.EdsRelease(stream);
EDSDK.EdsRelease(streamPtr);
else
throw new CameraDownloadException("Unable to get resultant image.", err);
【讨论】:
谢谢,有时我收到一个错误:在类型为“testcamera1!EDSDKLib.EDSDK+EdsObjectEventHandler::Invoke”的垃圾收集委托上进行了回调。这可能会导致应用程序崩溃、损坏和数据丢失。将委托传递给非托管代码时,托管应用程序必须使它们保持活动状态,直到保证它们永远不会被调用。 @ulduz114 我也一直这样。我所做的是为EdsObjectEventHandler
创建一个复杂的实例变量。正在发生的事情是委托被收集并且您丢失了参考。你需要坚持参考,直到你真正完成。我所做的是创建了一个 Camera 对象的抽象。它是一个单例对象,抽象了 Canon SDK 的状态和行为。在那里,我为私有 EdsObjectEventHandler 委托创建了一个实例变量。
谢谢,如果我的相机没有存储卡,我们如何将图像传输到电脑?
@ulduz114。 SDK(据我所知)仅以相机文件系统(即SD卡)上创建的对象的形式公开拍照事件。没有一种我熟悉的从缓冲区捕获的方法。从某种意义上说,这是有道理的,因为在只有少量板载内存的环境中,保持易失性内存畅通非常重要,这样它才能继续拍照。一旦缓冲区被刷新到非易失性内存中,您就可以与这些字节进行交互了。限制,我知道,但它就是这样。
@ulduz114:您的问题已在***.com/questions/3796658/…得到答复以上是关于使用edsdk 2.8拍照并直接将图像保存到PC的主要内容,如果未能解决你的问题,请参考以下文章