声明Color时的位图和OutOfMemory异常[8408,8337]

时间:2014-10-11 04:02:56

标签: c# arrays memory bitmap

基本上我的程序是用最简单的嵌套循环逐像素搜索另一个图像中的图像。 它适用于在9x9图像中查看2x2,但它无法在8408 x 8337分辨率下搜索(我想我不需要那么多,但我想检查它会有多慢)

声明Color 2D数组时发生错误 所以我要求帮助,因为为什么,以及如何解决这个问题

我怀疑OOM错误是由于SizeOfColorType * 8337比Int32大...但我不确定这是否正确

enter image description here

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Drawing;

namespace IMGReach
{
    class Program
    {
        static void Main(string[] args)
        {

            String basePath = @"C:\Users\Administrator\Desktop\IMGReachImages\1.jpg";       // 8408x8337
            String searchPath = @"C:\Users\Administrator\Desktop\IMGReachImages\2.jpg";     // 69 x 56

            Bitmap b = new Bitmap(basePath);        // base image
            Bitmap s = new Bitmap(searchPath);      // image to search inside of base image

            var x = ImageInImage(b, s);
            Console.WriteLine(x[0]);    // x coord of found image
            Console.WriteLine(x[1]);    // y coord of found image
            Console.Write("END");
            Console.ReadKey();
        }

        private static int[] ImageInImage(Bitmap source, Bitmap searchIt)
        {
            // Creates array of colors based on image
            Color[,] basePixels = AreaToArray(source, 0, 0, source.Width, source.Height);
            Color[,] searchPixels = AreaToArray(searchIt, 0, 0, searchIt.Width, searchIt.Height);

            Color hookPixel = searchPixels[0, 0];

            for (int xpos = 0; xpos < basePixels.GetLength(0); xpos++)
            {
                for (int ypos = 0; ypos < basePixels.GetLength(1); ypos++)
                {
                    if (basePixels[xpos, ypos] == hookPixel)
                    {
                        Color[,] checkMap = AreaToArray(source, xpos, ypos, searchIt.Width, searchIt.Height);
                        if (sameArray(checkMap, searchPixels))
                            return new int[] { xpos, ypos };
                    }
                }
            }

            return null;
        }

        private static Color[,] AreaToArray(Bitmap source, int start_x, int start_y, int width, int height)
        {
            if (start_x < 0)
                throw new ArgumentException("Invalid parameter value (less than zero)", "start_x");

            if (start_y < 0)
                throw new ArgumentException("Invalid parameter value (less than zero)", "start_y");

            if (width > source.Width)
                throw new ArgumentException("Width parameter is bigger than source width", "width");

            if (height > source.Height)
                throw new ArgumentException("Height parameter is bigger than source height", "height");

            Color[,] pixelSet = new Color[width, height];   // [2,2]

            for (int ix = 0; ix < width; ix++ )
                for (int iy = 0; iy < height; iy++)
                    pixelSet[ix, iy] = source.GetPixel(ix + start_x, iy + start_y);

            return pixelSet;
        }

        private static bool sameArray(int[,] a1, int[,] a2)
        {

            if (a1.GetLength(0) != a2.GetLength(0))
                return false;

            if (a1.GetLength(1) != a2.GetLength(1))
                return false;

            for (int i = 0; i < a1.GetLength(0); i++)
            {
                for (int j = 0; j < a1.GetLength(1); j++)
                {
                    if (a1[i, j] == a2[i, j])
                    {
                        continue;

                    }
                    else
                    {
                        return false;
                    }
                }
            }

            return true;
        }

        private static bool sameArray(Color[,] a1, Color[,] a2)
        {
            if (a1.GetLength(0) != a2.GetLength(0))
                return false;

            if (a1.GetLength(1) != a2.GetLength(1))
                return false;

            for (int i = 0; i < a1.GetLength(0); i++)
            {
                for (int j = 0; j < a1.GetLength(1); j++)
                {
                    if (a1[i, j] == a2[i, j])
                    {
                        continue;
                    }
                    else
                    {
                        return false;
                    }
                }
            }

            return true;
        }

    }

}

1 个答案:

答案 0 :(得分:2)

图像8408 x 8337包含超过7000万像素。 Color结构的大小至少为4个字节。因此,您尝试分配至少280兆字节。您的系统必须具有280兆字节的连续内存。如果您在32位系统上运行(或以32位模式运行程序),很可能您没有可用的内存。因此,OutOfMemoryException

情况变得更糟。即使您以某种方式设法为该映像分配内存,您的ImageInImage方法也需要分配basePixels数组,该数组大小相同。

您现在可能已经注意到即使在小图片上您的程序也很慢。使用GetPixel读取图像颜色会非常慢。您需要查看使用Bitmap.LockBits,以便可以直接访问图像位。那个MSDN主题有一个基本的例子。如果你想有效地使用它,你需要了解一些内部位图结构,但如果你搜索一下,有很多例子可用。