2009-07-05 6 views
2

Я уже некоторое время сражаюсь с Canon EDSDK. Я могу успешно получить библиотеку, чтобы сохранить файл непосредственно на диск, однако я не могу ухватить изображение байта [] в памяти. Всякий раз, когда я пытаюсь маршал.Copy() поток EDSDK в байт [], я всегда получаю следующую ошибку:Canon EDSDK MemoryStream Изображение

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

Breakpoints раскрыть (через объект EdsDirectoryItemInfo), что изображение является действительно есть, я просто дон Я знаю, почему я получаю исключение, которое я есть. Я играл с идеей принять поражение и просто прочитал результирующий образ с диска, который он так легко пишет с помощью метода CreateFileStream, но мне действительно нужно просто управлять изображением в памяти.

Любые идеи?

UPDATE: Я вижу это поведение в обеих версиях 2.5 и 2.6.

+0

Вы не возражаете размещения кода (где-то), чтобы загрузить изображение, которое вы только что взяли на диск? Я даже не могу зайти так далеко. В частности, я не могу заставить его вызвать функцию обработчика событий объекта. – andrewrk

ответ

4

Я просто искал Google для EdsCreateMemoryStream и found a sample, в котором есть еще один вызов, чтобы получить указатель из «потока памяти».

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

Вы можете использовать pointerToBytes в качестве источника для чтения из в Marshal.Copy.

Таким образом, я бы предположил, что то, что вы сейчас делаете, это попытка скопировать большое количество байтов, начиная с адреса какой-либо небольшой структуры управления, на которую указывает stream, и, следовательно, вы читаете это до конца этого состав.

Редактировать: Кстати, вы код выглядит так, как будто кто-то сказал вам, что вы должны иметь только один оператор возврата! Это старый совет, касающийся таких языков, как Fortran и C; это не имеет смысла в современных языках. Ваш код будет понятнее (по крайней мере, в данном случае), если вы немедленно возвратил код ошибки каждый раз, когда вы получили отказ:

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

(еще лучше, бросить конкретный класс исключений, содержащий код ошибки и строку, объясняющую что вы пытались сделать.)

+0

Этот конкретный метод - это всего лишь метод обертки (тестовый для этого) для EDSDK, поэтому он отметил. Я дам указателю прочитать попытку, когда я вернусь домой. –

3

Я понимаю, что это старый пост, но это полный фрагмент 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; 
     } 
Смежные вопросы