创建位图 C# 时出现 OutOfMemory 异常

OutOfMemory Exception when creating a bitmap C#

所以如果我错了请纠正我,那里已经有一个重复的 - 但我花了过去几个小时在堆栈中拖网和绞尽脑汁,我似乎无法解决这个问题。

我已经编写了一个基本的、单线程的、递归的文件爬行系统,它将查找它可以找到的任何图像文件并将其路径加载到一个数组中。然后将数组传递给一个方法,该方法遍历数组并检查每个图像的大小 (H,W) - 如果满足最低要求,则将其保存到新的最终数组中,如果不满足,则为直接忽略了。

我已尝试使用 USING 语句创建我的所有位图,以确保创建尽可能少的垃圾...但是,我仍然遇到内存不足异常。这是我的代码片段:

foreach (string current in scaledList)
{
    using (Bitmap bitmap = new Bitmap(current))
    {
        Bitmap bitmap2 = bitmap;
        float num5 = (float)(bitmap.Width / num2 * (bitmap.Height / num2));
        float num6 = (float)Vision.DetectSkin(bitmap, ref bitmap2, num2, iValue, hueMin, hueMax);
        num7 = num6 / num5 * 100f;
        bitmap2.Dispose();
    }
}

被窃听并抛出异常的行是:

using (Bitmap bitmap = new Bitmap(current))

这很有趣,因为程序在 Vision.DetectSkin 方法未被调用时运行。然而 - 在完成文件抓取和缩放处理后,只有当 Vision class 未被注释掉时,违规行才会抛出错误。

无论如何,我们将不胜感激!提前致谢

如果您提到 Vision.DetectSkin 来自 http://www.codeproject.com/Articles/8127/Skin-Recognition-in-C,那将会很有帮助。

这是有问题的代码,为简洁起见删除了注释。请注意,它在第一行创建了一个 Graphics 对象,但根本没有使用它。 Graphics 实现了 IDisposable 但它没有被释放;换句话说,代码将位图加载为另一种格式,什么也不做,然后不处理它。我会尝试删除该行,看看您的问题是否消失。

仅仅因为它在 CodeProject 上并不意味着它是好的、经过测试和调试的代码...

    public static void DetectSkin(Bitmap original, ref Bitmap modified)
    {
        Graphics g = Graphics.FromImage(original);
        ArrayList points = new ArrayList();
        for (Int32 x = 0; x < original.Width; x++)
        {
            for (Int32 y = 0; y < original.Height; y++)
            {
                Color c = modified.GetPixel(x, y);

                double I = (Math.Log(c.R) + Math.Log(c.B) + Math.Log(c.G)) / 3;
                double Rg = Math.Log(c.R) - Math.Log(c.G);
                double By = Math.Log(c.B) - (Math.Log(c.G) + Math.Log(c.R)) / 2;
                double hue = Math.Atan2(Rg, By) * (180 / Math.PI);

                if (I <= 5 && (hue >= 4 && hue <= 255))
                {
                    points.Add(new Point(x, y));
                }
                else
                {
                    modified.SetPixel(x, y, Color.Black);
                }
            }
        }
    }