佳能 EDSDK ObjectEvent_DirItemRequestTransfer

发布于 2024-11-25 22:53:27 字数 3962 浏览 1 评论 0原文

我的 C# 应用程序每 3 分钟拍摄一张图像,每次都按预期从 EDSDK 获取图像。我的问题是应用程序每次拍摄都会泄漏大约 5 MB,我非常确定问题出在 EDSDK 上。

代码:

    private uint CameraObjectEvent(uint inEvent, IntPtr inRef, IntPtr inContext)
    {
        switch (inEvent)
        {
            case EDSDK.ObjectEvent_DirItemRequestTransfer:
                GetCapturedItem(inRef);
                break;
        }

        return EDSDKErrorCodes.EDS_ERR_OK;
    }

    private void GetCapturedItem(IntPtr directoryItem)
    {
        uint error = EDSDKErrorCodes.EDS_ERR_OK;
        IntPtr stream = IntPtr.Zero;

        //Get information of the directory item.
        EDSDK.EdsDirectoryItemInfo dirItemInfo;
        error = EDSDK.EdsGetDirectoryItemInfo(directoryItem, out dirItemInfo);
        if (error != EDSDKErrorCodes.EDS_ERR_OK)
        {
            OnCameraErrorRaised(error, "EDSDK.EdsGetDirectoryItemInfo failed.");
            return;
        }

        //Create a file stream for receiving image.
        error = EDSDK.EdsCreateMemoryStream(dirItemInfo.Size, out stream);
        if (error != EDSDKErrorCodes.EDS_ERR_OK)
        {
            OnCameraErrorRaised(error, "EDSDK.EdsCreateMemoryStream failed");
            return;
        }

        //Fill the stream with the resulting image
        error = EDSDK.EdsDownload(directoryItem, dirItemInfo.Size, stream);
        if (error != EDSDKErrorCodes.EDS_ERR_OK)
        {
            OnCameraErrorRaised(error, "EDSDK.EdsDownload failed.");
            return;
        }

        error = EDSDK.EdsDownloadComplete(directoryItem);
        if (error != EDSDKErrorCodes.EDS_ERR_OK)
        {
            OnCameraErrorRaised(error, "EDSDK.EdsDownloadComplete failed.");
            return;
        }

        //Copy the stream to a byte[]
        IntPtr pointerToBytes = IntPtr.Zero;
        EDSDK.EdsGetPointer(stream, out pointerToBytes);

        MemoryStream imageStream = null;
        Image image = null;

        try
        {
            byte[] buffer = new byte[dirItemInfo.Size];
            GCHandle gcHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
            Marshal.Copy(pointerToBytes, buffer, 0, (int)dirItemInfo.Size);

            //Create a MemoryStream and return the image
            imageStream = new MemoryStream(buffer);
            image = Image.FromStream(imageStream);
        }
        catch (Exception ex)
        {
            OnCameraErrorRaised(999999, string.Format("Failed while retrieving image from camera. Exception: {0}.", ex.Message));
        }
        finally
        {
            if (imageStream != null)
                imageStream.Dispose();
        }

        //If image was captured then send ImageCaptured event
        if (image != null)
            OnImageCaptured(image);

        //Clean up
        EDSDK.EdsRelease(pointerToBytes);
        pointerToBytes = IntPtr.Zero;

        EDSDK.EdsRelease(stream);
        stream = IntPtr.Zero;

        EDSDK.EdsRelease(directoryItem);
        directoryItem = IntPtr.Zero;
    }

OnImageCaptured(image) 行只是将图像发送到控制器,该控制器将来自相机的图像与另一个图像合并,然后在保存最终合并图像后处理这两个图像:

    private void ImageCaptured(Image originalImage)
    {
        Image watermark = null;

        //Merge images
        try
        {
            watermark = Image.FromFile(Settings.Default.ImageWatermarkFilename);
            _imageController.Merge(originalImage, watermark);
            _imageController.SaveImage(originalImage);
        }
        catch (Exception ex)
        {
            LogManager.Instance.UpdateLog(string.Format("Error - Failed to merge and save images. Exception: {0}.", ex.Message));

            //HACK:
            System.Windows.Forms.Application.Restart();
            App.Current.Shutdown(); 
        }
        finally
        {
            originalImage.Dispose();
            if (watermark != null)
                watermark.Dispose();
        }
    }

那么为什么应用程序内存泄漏 - 有什么想法吗?

/干杯

My C# application is shooting an image every 3 minutes and I get the image from the EDSDK as expected every time. My problem is that the application is leaking about 5 mb for every shot and Iøm very sure that the problem is the EDSDK.

Code:

    private uint CameraObjectEvent(uint inEvent, IntPtr inRef, IntPtr inContext)
    {
        switch (inEvent)
        {
            case EDSDK.ObjectEvent_DirItemRequestTransfer:
                GetCapturedItem(inRef);
                break;
        }

        return EDSDKErrorCodes.EDS_ERR_OK;
    }

    private void GetCapturedItem(IntPtr directoryItem)
    {
        uint error = EDSDKErrorCodes.EDS_ERR_OK;
        IntPtr stream = IntPtr.Zero;

        //Get information of the directory item.
        EDSDK.EdsDirectoryItemInfo dirItemInfo;
        error = EDSDK.EdsGetDirectoryItemInfo(directoryItem, out dirItemInfo);
        if (error != EDSDKErrorCodes.EDS_ERR_OK)
        {
            OnCameraErrorRaised(error, "EDSDK.EdsGetDirectoryItemInfo failed.");
            return;
        }

        //Create a file stream for receiving image.
        error = EDSDK.EdsCreateMemoryStream(dirItemInfo.Size, out stream);
        if (error != EDSDKErrorCodes.EDS_ERR_OK)
        {
            OnCameraErrorRaised(error, "EDSDK.EdsCreateMemoryStream failed");
            return;
        }

        //Fill the stream with the resulting image
        error = EDSDK.EdsDownload(directoryItem, dirItemInfo.Size, stream);
        if (error != EDSDKErrorCodes.EDS_ERR_OK)
        {
            OnCameraErrorRaised(error, "EDSDK.EdsDownload failed.");
            return;
        }

        error = EDSDK.EdsDownloadComplete(directoryItem);
        if (error != EDSDKErrorCodes.EDS_ERR_OK)
        {
            OnCameraErrorRaised(error, "EDSDK.EdsDownloadComplete failed.");
            return;
        }

        //Copy the stream to a byte[]
        IntPtr pointerToBytes = IntPtr.Zero;
        EDSDK.EdsGetPointer(stream, out pointerToBytes);

        MemoryStream imageStream = null;
        Image image = null;

        try
        {
            byte[] buffer = new byte[dirItemInfo.Size];
            GCHandle gcHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
            Marshal.Copy(pointerToBytes, buffer, 0, (int)dirItemInfo.Size);

            //Create a MemoryStream and return the image
            imageStream = new MemoryStream(buffer);
            image = Image.FromStream(imageStream);
        }
        catch (Exception ex)
        {
            OnCameraErrorRaised(999999, string.Format("Failed while retrieving image from camera. Exception: {0}.", ex.Message));
        }
        finally
        {
            if (imageStream != null)
                imageStream.Dispose();
        }

        //If image was captured then send ImageCaptured event
        if (image != null)
            OnImageCaptured(image);

        //Clean up
        EDSDK.EdsRelease(pointerToBytes);
        pointerToBytes = IntPtr.Zero;

        EDSDK.EdsRelease(stream);
        stream = IntPtr.Zero;

        EDSDK.EdsRelease(directoryItem);
        directoryItem = IntPtr.Zero;
    }

The line OnImageCaptured(image) just sends the image to a controller which merges the image from the camera with another image and then disposes both images after saving the finale merged image:

    private void ImageCaptured(Image originalImage)
    {
        Image watermark = null;

        //Merge images
        try
        {
            watermark = Image.FromFile(Settings.Default.ImageWatermarkFilename);
            _imageController.Merge(originalImage, watermark);
            _imageController.SaveImage(originalImage);
        }
        catch (Exception ex)
        {
            LogManager.Instance.UpdateLog(string.Format("Error - Failed to merge and save images. Exception: {0}.", ex.Message));

            //HACK:
            System.Windows.Forms.Application.Restart();
            App.Current.Shutdown(); 
        }
        finally
        {
            originalImage.Dispose();
            if (watermark != null)
                watermark.Dispose();
        }
    }

So why does the app memory leak - any ideas?

/Cheers

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

薔薇婲 2024-12-02 22:53:27

释放您的GCHandle。它是每次拍摄时消耗内存的罪魁祸首

gcHandle.Free()

release your GCHandle. it is the culprit eating memory every time when you are taking shoot

gcHandle.Free()

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文