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