【问题标题】:take picture and directly save image to pc using edsdk 2.8使用edsdk 2.8拍照并直接将图像保存到PC
【发布时间】:2010-09-21 16:46:56
【问题描述】:

我是 EDSDK 2.8 的新手

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

有人有什么想法吗?或者 c# 或 vb.net 中的示例代码?

【问题讨论】:

    标签: c# .net image edsdk


    【解决方案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:您的问题已在stackoverflow.com/questions/3796658/…得到答复
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-30
      相关资源
      最近更新 更多