1

我有这个小方法,可以调整图像大小并裁剪它,但是在它工作了几个小时后,它突然开始给我 OutOfMemory 异常。我究竟做错了什么?我认为异常已开启return bmp.Clone(cropArea, bmp.PixelFormat);

    private static Bitmap Resize(Bitmap image, int width, int height)
    {
        double scaleH = (double)height / image.Height;
        double scaleW = (double)width / image.Width;
        double scale = 1.0;
        if (image.Width * scaleH >= width)
            scale = scaleH;
        else if (image.Height * scaleW >= height)
            scale = scaleW;

        var scaleWidth = (int)(image.Width * scale);
        var scaleHeight = (int)(image.Height * scale);

        using (var bmp = new Bitmap((int)scaleWidth, (int)scaleHeight))
        {
            using (var graph = Graphics.FromImage(bmp))
            {
                graph.DrawImage(image, new Rectangle(0, 0, scaleWidth, scaleHeight));
            }
            int xStart = (bmp.Width - width) / 2;
            int yStart = (bmp.Height - height) / 2;
            Rectangle cropArea = new Rectangle(xStart, yStart, width, height);
            return bmp.Clone(cropArea, bmp.PixelFormat);
        }
    }

解决方案这是一个舍入问题,裁剪矩形比它自己的图像大

    var scaleWidth = (int)Math.Ceiling(image.Width * scale);
    var scaleHeight = (int)Math.Ceiling(image.Height * scale);
4

1 回答 1

1

最初我认为这是因为您在原始问题中遇到的内存泄漏

Bitmap target = new Bitmap(width, height);
...
target = bmp.Clone(cropArea, bmp.PixelFormat);

您需要将克隆分配给临时变量,处置实例目标指向的然后返回目标。

如果您确实将目标用于您想要执行的操作

temp = bmp.Clone(cropArea, bmp.PixelFormat);
target.Dipose();
target = temp;

但是你注意到这不再是问题(你更新的例子没有这个问题)从我可以告诉你问题中的代码似乎不是问题,你可能有内存泄漏,MSDN有更多信息关于它在这里。如果您提供使用包装非托管资源的对象的代码,我可能能够确定它是否是内存泄漏。

另一种可能性

位图也可能太大以至于您的程序可用内存不足,如果您可以让我们知道有关程序失败的位图的更多信息,这将更容易判断

于 2013-07-05T18:50:37.477 回答