Pergunta

Eu tenho lutado com a Canon EDSDK por um tempo agora. Eu posso conseguir obter a biblioteca para salvar um arquivo diretamente para o disco, no entanto, não pode obter um porão do byte de imagem [] na memória. Sempre que eu tentar Marshal.Copy () o EDSDK Stream para byte [], eu sempre obter o seguinte erro:

AccessViolationException: Tentativa de ler ou memória protegida gravação. Isso é muitas vezes uma indicação de que outra memória está corrompida.

A seguir é uma das variações do código que eu usei para tentar obter a corrente:

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

Pontos de interrupção revelar (através do objeto EdsDirectoryItemInfo) que a imagem é realmente lá, eu só não sei por que eu estaria começando a exceção que eu sou. Eu tenho sido brincando com a idéia de aceitar a derrota e acabou de ler a imagem resultante do disco que tão prontamente escreve através do método CreateFileStream, mas eu realmente deveria apenas ser capaz de manipular a imagem na memória.

Todas as idéias?

UPDATE: eu ver esse comportamento em ambas as versões 2.5 e 2.6

.
Foi útil?

Solução

Eu só pesquisei para EdsCreateMemoryStream e encontrou um amostra em que há uma outra chamada para obter o ponteiro do" fluxo de memória ".

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

Você pode então usar pointerToBytes como fonte de ler em Marshal.Copy.

Então, eu acho que o que você está fazendo atualmente está tentando copiar algum grande número de bytes a partir do endereço de alguma estrutura de controle pequena apontado por stream, e, portanto, você está lendo após o final dessa estrutura .

Editar: A propósito, você olha código como se alguém lhe disse que você só deve ter uma instrução de retorno! Isso é velho conselho relativo a linguagens como Fortran e C; não faz sentido em línguas modernas. Seu código seria mais clara (pelo menos neste caso) se você imediatamente devolveu o código de erro cada vez que você tem uma falha:

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

(Melhor ainda, lançar uma classe de exceção específica que contém o código de erro e uma série explicando o que você estava tentando fazer.)

Outras dicas

Eu percebo que este é um post antigo, mas este é um C # trecho completo para download a partir de um fluxo de memória. Pode ser útil para alguém. As necessidades da câmera para ser configurada para 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;
        }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top