[英]Canon EDSDK MemoryStream Image
I've been fighting with the Canon EDSDK for a while now. 我一直在与佳能EDSDK作战。 I can successfully get the library to save a file directly to disk, however, I cannot get a hold of the image byte[] in memory. 我可以成功地获得将文件直接保存到磁盘的库,但是,我无法在内存中保留图像byte []。 Whenever I attempt to Marshal.Copy() the EDSDK Stream to byte[], I always get the following error: 每当我尝试将EDSDK流编组为byte []时,总是会出现以下错误:
AccessViolationException: Attempted to read or write protected memory. AccessViolationException:尝试读取或写入受保护的内存。 This is often an indication that other memory is corrupt. 这通常表明其他内存已损坏。
Below is one of the variations of code that I've used to try and get the stream: 以下是我用来尝试获取流的代码的变体之一:
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;
}
Breakpoints reveal (Through the EdsDirectoryItemInfo object) that the image is indeed there, I just don't know why I'd be getting the exception that I am. 断点显示(通过EdsDirectoryItemInfo对象)图像确实存在,我只是不知道为什么我会得到我自己的异常。 I have been toying with the idea of accepting defeat and just read the resultant image from disk that it so readily writes via the CreateFileStream method, but I really ought to just be able to manipulate the image in memory. 我一直在接受接受失败的想法,只是从磁盘读取生成的图像,这样就很容易通过CreateFileStream方法写入该图像,但是我真的应该只能够操作内存中的图像。
Any ideas? 有任何想法吗?
UPDATE: I see this behavior in both versions 2.5 and 2.6. 更新:我在版本2.5和2.6中都看到了此行为。
I just googled for EdsCreateMemoryStream
and found a sample in which there's another call to get the pointer from the "memory stream". 我只是在EdsCreateMemoryStream
搜索了EdsCreateMemoryStream
并找到了一个示例,在该示例中还有另一个调用以从“内存流”中获取指针。
IntPtr pointerToBytes;
EDSDKLib.EDSDK.EdsGetPointer(stream, out pointerToBytes);
You can then use pointerToBytes
as the source to read from in Marshal.Copy
. 然后,可以在Marshal.Copy
使用pointerToBytes
作为要读取的源。
So I'd guess that what you're currently doing is attempting to copy some large number of bytes starting from the address of some small control structure pointed to by stream
, and hence you're reading past the end of that structure. 因此,我想您当前正在做的是尝试从stream
指向的一些小型控制结构的地址开始复制大量字节,因此您正在读取该结构的末尾。
Edit: By the way, you're code looks as if someone's told you that you should only have one return statement! 编辑:顺便说一句,您的代码看起来好像有人告诉您只应有一个return语句! That's old advice relating to languages like Fortran and C; 这是与Fortran和C等语言有关的旧建议; it doesn't make sense in modern languages. 在现代语言中这没有意义。 Your code would be clearer (at least in this case) if you immediately returned the error code every time you got a failure: 如果您每次遇到故障都立即返回错误代码,则您的代码将更加清晰(至少在这种情况下):
if ((err = EDSDK.EdsBlahBlah(...)) != EDSDK.EDS_ERR_OK)
return err;
(Better yet, throw a specific exception class containing the error code and a string explaining what you were trying to do.) (更好的是,抛出一个特定的异常类,其中包含错误代码和说明您要执行的操作的字符串。)
I realize that this is an old post, but this is a complete C# snippet for downloading from a memory stream. 我意识到这是一篇老文章,但这是用于从内存流下载的完整C#代码段。 It may be useful for someone else. 这对其他人可能有用。 The camera needs to be set to EDSDK.EdsSaveTo.Host or EDSDK.EdsSaveTo.Both 摄像机需要设置为EDSDK.EdsSaveTo.Host或EDSDK.EdsSaveTo.Both
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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.