2009-07-05 3 views
2

Je me bats avec le Canon EDSDK depuis un moment. Je peux obtenir avec succès la bibliothèque pour enregistrer un dossier directement sur le disque, cependant, je ne peux pas obtenir l'octet d'image [] dans la mémoire. Chaque fois que je tente Marshal.Copy() le flux EDSDK à byte [], j'obtiens toujours l'erreur suivante:Canon Image EDSDK MemoryStream

AccessViolationException: Tentative de lecture ou d'écriture de la mémoire protégée. C'est souvent une indication que l'autre mémoire est corrompue.

Ci-dessous est l'une des variantes de code que j'ai utilisé pour essayer d'obtenir le flux:

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

révèlent les points d'arrêt (à travers l'objet EdsDirectoryItemInfo) que l'image est bien là, je viens de don Je ne sais pas pourquoi je recevrais l'exception que je suis. J'ai joué avec l'idée d'accepter la défaite et juste lu l'image résultante à partir du disque qu'il écrit si facilement via la méthode CreateFileStream, mais je devrais juste être capable de manipuler l'image en mémoire.

Des idées?

MISE À JOUR: je vois ce comportement dans les versions 2.5 et 2.6.

+0

-vous l'esprit poster votre code (quelque part) pour télécharger l'image que vous venez de prendre sur le disque? Je ne peux même pas aller aussi loin. Plus précisément, je n'arrive pas à appeler ma fonction de gestionnaire d'événement d'objet. – andrewrk

Répondre

4

Je viens de googler pour EdsCreateMemoryStream et found a sample dans lequel il y a un autre appel pour obtenir le pointeur du "flux de la mémoire".

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

Vous pouvez ensuite utiliser pointerToBytes comme source pour lire en Marshal.Copy.

Donc, je suppose que ce que vous faites actuellement est de tenter de copier un grand nombre d'octets à partir de l'adresse d'une structure de contrôle petite pointée par stream, et donc vous lisez après la fin de cette structure. A propos, vous avez l'impression que quelqu'un vous a dit que vous ne devriez avoir qu'une seule instruction de retour! C'est vieux conseil concernant des langues comme Fortran et C; cela n'a pas de sens dans les langues modernes. Votre code serait plus clair (au moins dans ce cas) si vous immédiatement retourné le code d'erreur chaque fois que vous avez un échec:

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

(Mieux encore, lancer une classe d'exception spécifique contenant le code d'erreur et une chaîne expliquant ce que vous essayiez de faire.)

+0

Cette méthode particulière est juste une méthode wrapper (un test à cela) pour l'EDSDK, donc noté duelly. Je vais essayer le pointeur en rentrant chez moi. –

3

Je me rends compte qu'il s'agit d'un ancien article, mais il s'agit d'un extrait complet de C# à télécharger à partir d'un flux de mémoire. Cela peut être utile pour quelqu'un d'autre. La caméra doit être réglé sur EDSDK.EdsSaveTo.Host ou 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; 
     } 
Questions connexes