的形象.rotatflip内存泄漏:/

本文关键字:泄漏 内存 rotatflip | 更新日期: 2023-09-27 18:01:21

虽然我已经编程了大约11年(主要是VB6,最近6个月c#),这是第一次真正问一个问题:)我已经从互联网上找到了我所有的答案,但这个问题我不能自己解决。你的网站是最有帮助的地方之一,我得到了最好的答案!

我将显示我正在使用的代码(相关内容的摘录)。问题是,当使用rotatflip方法时,内存迅速增加到~200M,然后在一段时间后由GC收集。调用它的main方法每秒迭代大约30次,所以性能在这里是最重要的。我曾尝试使用图形矩阵变换,但这有时会失败,并显示非翻转图像。应用程序本身是基于使用网络摄像头,隐藏预览,拍摄回调图片,并显示在图片框。然后从另一个类中叠加一个矩形。这就是使用回调而不是预览窗口的原因。

Capture.cs类:

internal Bitmap LiveImage;
    int ISampleGrabberCB.BufferCB(double bufferSize, IntPtr pBuffer, int bufferLen)
    {
        LiveImage = new Bitmap(_width, _height, _stride, PixelFormat.Format24bppRgb, pBuffer);
        if (ExpImg) // local bool, used rarely when the picture saving is triggered
        {
            LiveImage.RotateFlip(RotateFlipType.RotateNoneFlipY);
            var a = LiveImage.Clone(new Rectangle(Currect.Left, Currect.Top, Currect.Width, Currect.Height),
                                    LiveImage.PixelFormat);
            using (a)
                a.Save("ocr.bmp", ImageFormat.Bmp);
        }
        else // dmnit, rotateflip leaks like h*ll but matrix transform doesn't sometimes flip :S
        {
            LiveImage.RotateFlip(RotateFlipType.RotateNoneFlipY);
            /*using (var g = Graphics.FromImage(LiveImage))
            {
                g.Transform = _mtx;
                g.DrawImage(LiveImage, 0, 0);
            }*/
        }
        GC.Collect(); // gotta use it with rotateflip, otherwise it gets crazy big, like ~200M :O
        return 0;
    }
}

在主要形式,我有一个事件,更新图片在图片框:

private void SetPic()
{
    pctCamera.Image = _cam.LiveImage;
    _cam.PicIsFree = false;
}

因为我需要得到图像的主要形式,这是在另一个类,然后我认为最合乎逻辑的是暴露的位图,这是在每个回调帧更新。我不想使用矩阵变换的原因是因为它比较慢,有时在这个速度下它无法翻转图像,并且这种行为的频率与不同的PC具有不同的硬件能力和CPU速度是完全不同的,最快的帧率30fps与1.2GHz的CPU也经常显示这种情况。

那么,你能帮我弄明白吗?我实际上并没有在当前版本中使用它,我正在使用注释掉的矩阵变换,因为我觉得使用GC很糟糕。收集:(

谢谢! !

的形象.rotatflip内存泄漏:/

pctCamera.Image = _cam.LiveImage;

您所观察到的大量内存使用是一个明确的信号,表明您错过了在某处调用Dispose()的机会,让位图使用的非托管资源(主要是内存)提前释放,而不是让垃圾收集器执行。引用的语句就是这样一种情况,您没有处理由图片框引用的旧图像。解决办法:

if (pctCamera.Image != null) pctCamera.Image.Dispose();
pctCamera.Image = _cam.LiveImage;

你可以这样重写你的代码:

internal Bitmap LiveImage;
int ISampleGrabberCB.BufferCB(double bufferSize, IntPtr pBuffer, int bufferLen)
{
    using (LiveImage = new Bitmap(_width, _height, _stride, PixelFormat.Format24bppRgb, pBuffer))
    {
        LiveImage.RotateFlip(RotateFlipType.RotateNoneFlipY);
        if (ExpImg) // local bool, used rarely when the picture saving is triggered
        {
            var a = LiveImage.Clone(new Rectangle(Currect.Left, Currect.Top, Currect.Width, Currect.Height),
                                    LiveImage.PixelFormat);
            using (a)
                a.Save("ocr.bmp", ImageFormat.Bmp);
        }
    }
    return 0;
}

BitmapImage类,实现了IDispose。每次创建Bitmap时,我建议使用using语句自动释放资源。

GC。Collect是用来处理这种情况的。收集数据是释放它的唯一方法,当创建巨大的位图时,这是必经之路。执行GC。收集真的会减慢速度吗?

除此之外,你应该保持位图副本的数量尽可能低。