tags:

views:

159

answers:

2

Hello I'm new to this EDSDK 2.8

At the moment, my program can take pictures, However, when a picture is taken, that picture is temporarily stored in a buffer in the canon camera i would like to know how we could save it directory to PC?

Does anyone have any ideas? or a sample code with c# or vb.net?

thanks

+1  A: 

Here is what I have done:

First, you have to register for the callback event when an object is created (ie, a picture). I did this in a registerEvents method that I created:

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

The objectEventHandler is the method that will be called when a picture is created.

The method needs to conform to the interface dictated by the API. Here's an example implementation of that method:

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

In this example I turn around and spawn my own event, which has the reference to the stream object. This is handled by the following code:

        /// <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);
            }
        }
Wayne Hartman
thanks, sometimes i got a error :A callback was made on a garbage collected delegate of type 'testcamera1!EDSDKLib.EDSDK+EdsObjectEventHandler::Invoke'. This may cause application crashes, corruption and data loss. When passing delegates to unmanaged code, they must be kept alive by the managed application until it is guaranteed that they will never be called.
ulduz114
@ulduz114 I kept getting that too. What I did was create a pricate instance variable for the `EdsObjectEventHandler`. What's happening is that the delegate is getting collected and you've lost the reference. You will need to hold on to the reference until you are really done. What I did was created an abstraction of a Camera object. It is a singleton object that abstracts the state and behavior of the Canon SDK. There I created an instance variable for the private EdsObjectEventHandler delegate.
Wayne Hartman
thanks ,if my camera does not have memory card ,how could we transfer images to pc?
ulduz114
the objectEventHandler was not called when i remove the SD card from camera...
ulduz114
@ulduz114. The SDK (as far as I know) only exposes the picture taking event in the form of the object being created on the file system of the camera (ie the SD card). There is not a way of which I am familiar to capture from buffer. In a way this makes sense, because in an environment where there is only a small amount of onboard memory, it is important to keep the volatile memory clear so that it can continue to take photographs. Once the buffer has been flushed to nonvolatile memory, you are then clear to interact with those bytes. Limiting, I know, but it is what it is.
Wayne Hartman