【问题标题】:Out of memory error on Drawing bitmap background on picturebox在图片框上绘制位图背景时出现内存不足错误
【发布时间】:2014-07-31 17:18:41
【问题描述】:

这是我的问题:

此方法在 50 毫秒的计时器上重复。 从程序启动到及时转发,该进程的 RAM 内存不断增长,最后调试器将“内存不足错误”抛出到加粗的行(drawimage 方法)。

是否有人可以帮助我找到避免这种情况的解决方案并解释为什么会发生这种情况?

PS。我的目标是不断旋转图片框的背景图像。我知道也许我可以直接在表格上而不是在图片框上绘图,但是如果图片框有解决方案,我会很高兴:p

谢谢!

public static Bitmap RotateImage(Image image, PointF offset, float angle)
    {
        if (image == null)
            throw new ArgumentNullException("image");

        //create a new empty bitmap to hold rotated image
        Bitmap rotatedBmp = new Bitmap(image.Width, image.Height);
        rotatedBmp.SetResolution(image.HorizontalResolution, image.VerticalResolution);

        //make a graphics object from the empty bitmap
        Graphics g = Graphics.FromImage(rotatedBmp);

        //Put the rotation point in the center of the image
        g.TranslateTransform(offset.X, offset.Y);

        //rotate the image
        g.RotateTransform(angle);

        //move the image back
        g.TranslateTransform(-offset.X, -offset.Y);

        //draw passed in image onto graphics object
        **g.DrawImage(image, new PointF(0, 0));**

        return rotatedBmp;
    }

【问题讨论】:

    标签: c# bitmap background-image image-rotation


    【解决方案1】:

    您还需要 Dispose() 旧位图。

    想象一下你的代码是这样的:

    public static Bitmap RotateImage(Image image, PointF offset, float angle)
    {
        if (image == null)
            throw new ArgumentNullException("image");
    
        //create a new empty bitmap to hold rotated image
        Bitmap rotatedBmp = new Bitmap(image.Width, image.Height);
        rotatedBmp.SetResolution(image.HorizontalResolution, image.VerticalResolution);
        return rotatedBmp;
    }
    

    我尝试循环调用你的函数,但仍然失败!我不得不自己处理位图。我不清楚为什么 .NET 不清理它们。

    Image img = new Bitmap(@"some_image.png");
    PointF p = new PointF(0,0);
    for (int i=0; i<5000; i++)
    {
        Bitmap b = RotateImage(img, p, i % 360);
        b.Dispose(); // Fails if you don't do this!
    }
    

    【讨论】:

    • 当然,在您的情况下,您可能正在对位图进行操作,因此您需要保存最新的位图并在生成新的位图后将其丢弃。
    【解决方案2】:

    您的图形永远不会被释放,因此您正在泄漏内存。我认为你应该在绘制完图形后处理它,

    g.Dispose()

    您可能应该阅读一些有关 Idisposable 的信息以避免将来出现该问题,

    【讨论】:

    • 或使用using ( Graphics g = Graphics.FromImage(rotatedBmp))
    • 我认为当Graphics 对象超出范围时,它会被自动释放……为什么不是这样?
    • 它可能会处理掉它......最终。但是你画得太快了,我认为垃圾收集器赶不上!另见stackoverflow.com/questions/1572804/…
    • 我对 Idisposable 有所了解,事实上我已经尝试过使用和处置...但没有奏效!我以为图形“g”是在方法rotate image的末尾处理的!
    • @MobyDisk 好的。
    【解决方案3】:

    这就是解决方案!!!

    我必须同时处理图片框的背景图像和我每次创建的位图!

    谢谢大家!

        private void timer1_Tick(object sender, EventArgs e)
        {
            Image oldImage = RotateImage(
                pb_logoAfterLoad.BackgroundImage,
                offsetPoint,
                20);
    
            pb_logoAfterLoad.BackgroundImage.Dispose();
            pb_logoAfterLoad.BackgroundImage = (Image)oldImage.Clone();
    
            oldImage.Dispose();
    
        }
    

    【讨论】:

    • 需要克隆吗?你不能这样做: Image newImage = RotateImage(...);图片 oldImage = pb_logoAfterLoad.BackgroundImage; pb_logoAfterLoad.BackgroundImage = newImage; oldImage.Dispose();这样可以避免复制。
    猜你喜欢
    • 1970-01-01
    • 2012-12-30
    • 1970-01-01
    • 2013-08-27
    • 1970-01-01
    • 1970-01-01
    • 2012-12-12
    相关资源
    最近更新 更多