我一直战斗的Canon EDSDK一段时间了。我可以成功地得到图书馆保存的文件直接向盘,但是,我无法拿到的图像字节[]中的存储器。每当我试图元帅。Copy()该EDSDK流字节[],我总是得到以下错误:

AccessViolationException:试图阅读或写入受保护的存储器。这通常是指示,其他存储器是损坏。

下面是其中一个变化的代码,我已经用来尝试和获得流:

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

断点揭示(通过EdsDirectoryItemInfo对象)的图像确实是有的我只是不知道为什么我会变得异常,是我。我已经酝酿的想法接受失败,只是读取所得到的图像,从磁盘,它如此容易写通过CreateFileStream的方法,但是我真的应该只能够操纵的图像存储器中。

任何想法?

更新:我看到这种行为在两个版本2.5和2.6.

有帮助吗?

解决方案

我只是派对 EdsCreateMemoryStream发现了一个样本 在其存在的另一呼吁得到的指针,从"存储器流"。

IntPtr pointerToBytes;
EDSDKLib.EDSDK.EdsGetPointer(stream, out pointerToBytes);

然后可以使用 pointerToBytes 为源阅读自在 Marshal.Copy.

所以我猜这就是你目前所做的是试图复制一些大字节数从开始的地址的一些小控制结构指出,由 stream, 因此你读过去结束这一结构。

编辑: 顺便说一句,你们的代码看起来如果有人告诉你,你应该只有一个返回的声明!这是旧的建议有关的语言,如Fortran和C;这没有意义在现代语言。你的代码就可以更清楚地(至少在这种情况下),如果你立即返回的错误代码每次你得到了一个失败:

if ((err = EDSDK.EdsBlahBlah(...)) != EDSDK.EDS_ERR_OK)
    return err;

(更好的是,扔一个具体的例外类,其中包含的错误代码和一串解释什么是你们试图要做。)

其他提示

我认识到这是一个旧的文章,但是这是用于从存储器流下载一个完整的C#代码段。这可能是为别人有用。相机需要被设置为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归因
不隶属于 StackOverflow
scroll top