nehmen Bild und direkt speichern Bild auf den PC mit edsdk 2.8
Frage
Ich bin neu in den EDSDK 2.8
Im Moment kann mein Programm zu fotografieren. Wenn jedoch ein Bild aufgenommen wird, wird das Bild vorübergehend in einem Puffer in der Canon-Kamera gespeichert. Ich würde gerne wissen, wie es mit dem PC-Verzeichnis speichern?
Hat jemand eine Idee? Oder Beispielcode in C # oder vb.net?
Lösung
Hier ist, was ich getan habe:
Zuerst Sie für das Callback-Ereignis registrieren, wenn ein Objekt erstellt wird (dh ein Bild). Ich tue dies in einem Registerevent Methode, die ich erstellt:
// 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);
}
Die objectEventHandler
ist die Methode, die aufgerufen wird, wenn ein Bild erzeugt wird.
Die Methode muss an der Schnittstelle von der API diktiert anzupassen. Hier ist ein Beispiel-Implementierung dieser Methode:
/// <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 diesem Beispiel drehe ich mich um und mein eigenes Ereignis laichen, die den Verweis auf das Stream-Objekt hat. Dies wird durch den folgenden Code behandelt:
/// <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);
}
}
Andere Tipps
Ich tue das gleiche, dass ich keine Speicherkarte in der Kamera und das Bild auf die Host-Computer zu übertragen, nachdem der Take Bild Befehl gesendet wird. Hier ist, was für mich gearbeitet, den ObjectEventHandler
Rückruf aufgerufen zu erhalten, wenn keine Speicherkarte in der Canon EOS50D installiert ist.
EdsUInt32 setsaveto = kEdsSaveTo_Both;
err = EdsSetPropertyData(camera, kEdsPropID_SaveTo, 0, sizeof(setsaveto), &setsaveto);
Voila, wird der Rückruf aufgerufen, und ich kann dann fortfahren, die getCapturedItem()
Funktion zu tun, wie Wayne in der früheren Post geschrieben hat.