Domanda

Ho combattuto con la Canon EDSDK per un po '. Posso ottenere con successo la biblioteca per salvare un file direttamente su disco, però, non riesco a ottenere una sospensione del byte dell'immagine [] in memoria. Ogni volta che tento di Marshal.Copy () l'EDSDK Stream per byte [], ho sempre arrivare il seguente errore:

AccessViolationException: Tentativo di lettura o scrittura della memoria protetta. Ciò è spesso un'indicazione che l'altra memoria è corrotta.

Di seguito è una delle varianti di codice che ho usato per cercare di ottenere il flusso:

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

I punti di interruzione rivelano (attraverso l'oggetto EdsDirectoryItemInfo) che l'immagine è davvero lì, solo che non so perché mi piacerebbe essere sempre l'eccezione che io sono. Ho accarezzato l'idea di accettare la sconfitta e appena letto l'immagine risultante dal disco che scrive così facilmente tramite il metodo CreateFileStream, ma ho davvero dovrebbe essere solo in grado di manipolare l'immagine in memoria.

Tutte le idee?

UPDATE:. Vedo questo comportamento in entrambe le versioni 2.5 e 2.6

È stato utile?

Soluzione

Ho appena googled per EdsCreateMemoryStream e ha trovato un campione nel quale c'è un'altra chiamata per ottenere il puntatore del" flusso di memoria ".

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

È quindi possibile utilizzare pointerToBytes come fonte di leggere da in Marshal.Copy.

Quindi, direi che quello che stai facendo attualmente sta tentando di copiare alcuni gran numero di byte a partire dall'indirizzo di qualche piccola struttura di controllo puntata da stream, e quindi stai leggendo oltre la fine di quella struttura .

Modifica A proposito, sei codice è come se qualcuno ti ha detto che si dovrebbe avere una sola istruzione di ritorno! Questo è il vecchio consiglio in materia di linguaggi come Fortran e C; essa non ha senso in lingue moderne. Il tuo codice sarebbe più chiaro (almeno in questo caso) se si immediatamente restituito il codice di errore ogni volta che hai un fallimento:

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

(Meglio ancora, gettare una specifica classe di eccezione che contiene il codice di errore e una stringa che spiega quello che stavi cercando di fare.)

Altri suggerimenti

Mi rendo conto che questo è un vecchio post, ma questo è un completo C # frammento per il download da un flusso di memoria. Può essere utile per qualcun altro. La fotocamera deve essere impostato su EDSDK.EdsSaveTo.Host o 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;
        }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top