Canon Edsdk MemoryStream 이미지
문제
나는 지금 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;
}