Canon EDSDK Memory Bild
Frage
Ich habe jetzt eine Zeit lang mit der Canon EDSDK kämpfen. Ich kann erfolgreich die Bibliothek bekommen, um direkt auf der Festplatte eine Datei zu speichern, aber ich kann nicht halten, das Bild, byte [] im Speicher erhalten. Immer, wenn ich zu Marshal.Copy () dem EDSDK Strom versuchen, byte [], ich folgende Fehlermeldung immer erhalten:
Access: Versuchte zu geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass andere Speicher beschädigt ist.
Im Folgenden finden Sie eine der Änderungen des Codes, die ich verwendet habe, um zu versuchen, den Strom zu bekommen:
private uint downloadImage(IntPtr directoryItem)
{
uint err = EDSDK.EDS_ERR_OK;
IntPtr stream = IntPtr.Zero;
// Get information of the directory item.
EDSDK.EdsDirectoryItemInfo dirItemInfo;
err = EDSDK.EdsGetDirectoryItemInfo(directoryItem, out dirItemInfo);
// Create a file stream for receiving image.
if (err == EDSDK.EDS_ERR_OK)
{
err = EDSDK.EdsCreateMemoryStream(dirItemInfo.Size, out stream);
}
// Fill the stream with the resulting image
if (err == EDSDK.EDS_ERR_OK)
{
err = EDSDK.EdsDownload(directoryItem, dirItemInfo.Size, stream);
}
// Copy the stream to a byte[] and
if (err == EDSDK.EDS_ERR_OK)
{
byte[] buffer = new byte[dirItemInfo.Size];
GCHandle gcHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
// The following line is where it blows up...
Marshal.Copy(stream, buffer, 0, (int)dirItemInfo.Size);
// ... Image manipulation, show user, whatever
}
return err;
}
Haltepunkte zeigen (Durch das EdsDirectoryItemInfo Objekt), dass das Bild in der Tat gibt es, ich weiß nur nicht, warum ich die Ausnahme würde bekommen, was ich bin. Ich habe mit dem Gedanken Niederlage akzeptieren und habe gerade gelesen das sich ergebende Bild von der Festplatte, die es so leicht über die CreateFileStream Methode schreibt, aber ich sollte eigentlich nur in der Lage sein, das Bild im Speicher zu manipulieren.
Irgendwelche Ideen?
UPDATE:. Ich sehe dieses Verhalten in beiden Versionen 2.5 und 2.6
Lösung
Ich googeln nur für EdsCreateMemoryStream
und fand eine Probe , in dem es einen weiteren Anruf ist, um den Zeiger von dem bekommen" Speicher-Stream “.
IntPtr pointerToBytes;
EDSDKLib.EDSDK.EdsGetPointer(stream, out pointerToBytes);
Sie können dann als Quelle verwenden pointerToBytes
von in Marshal.Copy
zu lesen.
Also würde ich denke, dass das, was Sie gerade tun versucht, eine große Anzahl von Bytes von der Adresse von einiger kleinen Kontrollstruktur von stream
darauf beginnen zu kopieren, und daher sind Sie über das Ende dieser Struktur lesen .
Edit: By the way, sind Sie Code sieht aus, als wenn jemand Ihnen gesagt, dass Sie nur eine return-Anweisung haben sollte! Das ist alten Rat zu Sprachen wie Fortran und C beziehen; es macht keinen Sinn in der modernen Sprachen machen. Code wäre klarer (zumindest in diesem Fall), wenn Sie sofort den Fehlercode jedes Mal zurück Sie einen Fehler bekommen:
if ((err = EDSDK.EdsBlahBlah(...)) != EDSDK.EDS_ERR_OK)
return err;
(Noch besser wäre es, werfen eine bestimmte Ausnahmeklasse mit dem Fehlercode und eine Zeichenfolge zu erklären, was Sie tun wollten.)
Andere Tipps
Ich weiß, dass dies eine alte Post, aber das ist ein kompletter C # Code-Schnipsel, um aus einem Speicher-Stream herunterzuladen. Es kann für jemand anderen nützlich sein. Die Kamera muss EDSDK.EdsSaveTo.Host oder EDSDK.EdsSaveTo.Both zu setzen
uint error = EDSDK.EDS_ERR_OK;
IntPtr stream = IntPtr.Zero;
EDSDK.EdsDirectoryItemInfo directoryItemInfo;
error = EDSDK.EdsGetDirectoryItemInfo(this.DirectoryItem, out directoryItemInfo);
//create a file stream to accept the image
if (error == EDSDK.EDS_ERR_OK)
{
error = EDSDK.EdsCreateMemoryStream(directoryItemInfo.Size, out stream);
}
//down load image
if (error == EDSDK.EDS_ERR_OK)
{
error = EDSDK.EdsDownload(this.DirectoryItem, directoryItemInfo.Size, stream);
}
//complete download
if (error == EDSDK.EDS_ERR_OK)
{
error = EDSDK.EdsDownloadComplete(this.DirectoryItem);
}
//convert to memory stream
IntPtr pointer; //pointer to image stream
EDSDK.EdsGetPointer(stream, out pointer);
uint length = 0;
EDSDK.EdsGetLength(stream, out length);
byte[] bytes = new byte[length];
//Move from unmanaged to managed code.
Marshal.Copy(pointer, bytes, 0, bytes.Length);
System.IO.MemoryStream memoryStream = new System.IO.MemoryStream(bytes);
Image image = System.Drawing.Image.FromStream(memoryStream);
if (pointer != IntPtr.Zero)
{
EDSDK.EdsRelease(pointer);
pointer = IntPtr.Zero;
}
if (this.DirectoryItem != IntPtr.Zero)
{
EDSDK.EdsRelease(this.DirectoryItem);
this.DirectoryItem = IntPtr.Zero;
}
if (stream != IntPtr.Zero)
{
EDSDK.EdsRelease(stream);
stream = IntPtr.Zero;
}