2010-09-21 135 views
2

我是新来的EDSDK 2.8拍照并用edsdk直接保存图片到电脑2.8

目前我的程序可以拍照。但是,拍摄照片时,该照片会暂时存储在佳能相机的缓冲区中。我想知道如何将它保存到PC?

有没有人有任何想法?或在c#或vb.net中的示例代码?

回答

1

这里是我做了什么:

首先,你必须当一个对象被创建(即图片)回调事件进行注册。

// 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是在创建图像时将被调用的方法:我在registerEvents的方法,我创建了这样做。

该方法需要符合由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); 
      } 
     } 
+0

谢谢,有时我得到一个错误:回调是对'testcamera1!EDSDKLib.EDSDK + EdsObjectEventHandler :: Invoke'类型的垃圾收集委托进行的。这可能会导致应用程序崩溃,损坏和数据丢失。在将代理传递给非托管代码时,它们必须由托管应用程序保持活动状态,直到确保它们永远不会被调用。 – ulduz114 2010-09-22 18:09:44

+1

@ ulduz114我也一直在这样做。我所做的是为'EdsObjectEventHandler'创建一个pricate实例变量。发生的事情是,代表正在收集,你失去了参考。你将需要坚持参考,直到你真的完成。我所做的是创建了一个Camera对象的抽象。它是一个单例对象,可以抽象出Canon SDK的状态和行为。在那里,我为私有的EdsObjectEventHandler委托创建了一个实例变量。 – 2010-09-22 18:37:55

+0

谢谢,如果我的相机没有存储卡,我们如何将图像传输到PC? – ulduz114 2010-09-25 05:37:03

5

我做同样的,我在相机中没有存储卡并要发送的拍摄照片命令后的图像传输到主机。在Canon EOS50D中没有安装存储卡的情况下,我可以通过这种方式获得ObjectEventHandler的回叫。

EdsUInt32 setsaveto = kEdsSaveTo_Both; 
err = EdsSetPropertyData(camera, kEdsPropID_SaveTo, 0, sizeof(setsaveto), &setsaveto); 

瞧,回调函数被调用,然后我可以继续做getCapturedItem()功能韦恩已经张贴在先前的职位。