문제

나는 지금 Canon Edsdk와 잠시 동안 싸우고 있습니다. 파일을 디스크에 직접 저장하기 위해 라이브러리를 성공적으로 가져올 수는 있지만 메모리에서 이미지 바이트 []를 잡을 수는 없습니다. 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 IN에서 읽을 소스로 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