队列在洪水填充中丢失内存异常

时间:2013-05-25 19:39:57

标签: c# queue out-of-memory

我正在使用此处的代码对2000 x 2000 x 256位图(内存中)进行泛洪填充:http://rosettacode.org/wiki/Bitmap/Flood_fill#C.23

当q Count = 33554432(~33MB)时,队列丢失了内存错误。显然,我有更多的记忆。我还创建了一个IntPoint结构,所以每个点都是2个整数而不是2个双精度。

  1. 有没有办法为队列手动分配更多内存?
  2. 如果不可能,有人有任何其他建议吗?
  3. 仅供参考:我怀疑这是否很重要,但我实际上是在内存中填充2000 x 2000字节的数据,而不是实际加载位图,检查颜色和替换。

    下面是我从上面引用的链接实现的泛洪填充(可能会出现明显的错误):

    public struct IntPoint
        {
            public int X, Y;
    
            public IntPoint(int p1, int p2)
            {
                X = p1;
                Y = p2;
            }
        }
    
    
        public void TerrainFloodFill(Point Tpt, byte targetElevation, byte replacementTerrain)
        {
            IntPoint pt = new IntPoint((int)Tpt.X, (int)Tpt.Y);
    
            Queue<IntPoint> q = new Queue<IntPoint>();
            q.Enqueue(pt);
            while (q.Count > 0)
            {
                IntPoint n = q.Dequeue();
                if (HeightMap[(int)n.X, (int)n.Y] != targetElevation)
                    continue;
                IntPoint w = n, e = new IntPoint(n.X + 1, n.Y);
                while ((w.X > 0) && HeightMap[(int)w.X, (int)w.Y] == targetElevation)
                {
                    TerrainMap[(int)w.X, (int)w.Y] = replacementTerrain;
                    if ((w.Y > 0) && HeightMap[(int)w.X, (int)w.Y - 1] == targetElevation)
                        q.Enqueue(new IntPoint(w.X, w.Y - 1));
                    if ((w.Y < MapHeight - 1) && HeightMap[(int)w.X, (int)w.Y + 1] == targetElevation)
                        q.Enqueue(new IntPoint(w.X, w.Y + 1));
                    w.X--;
                }
                while ((e.X < MapWidth - 1) && HeightMap[(int)e.X, (int)e.Y] == targetElevation)
                {
                    TerrainMap[(int)e.X, (int)e.Y] = replacementTerrain;
                    if ((e.Y > 0) && HeightMap[(int)e.X, (int)e.Y - 1] == targetElevation)
                        q.Enqueue(new IntPoint(e.X, e.Y - 1));
                    if ((e.Y < MapHeight - 1) && HeightMap[(int)e.X, (int)e.Y + 1] == targetElevation)
                        q.Enqueue(new IntPoint(e.X, e.Y + 1));
                    e.X++;
                }
            }
    
        }
    

    一如既往,提前感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

这可能是一个碎片问题,你应该真的使用内存分析器来找出会发生什么。

作为第一次尝试,

  int estimatedSize = ...;
  Queue<IntPoint> q = new Queue<IntPoint>(estimatedSize);

我觉得int estimatedSize = MapWidth;之类的东西会是一个好的开始。


但你的队列仍然太大了。原始算法可能会在targetColor == replacementColor时失败,在您的情况下是HeightMap != TerrainMap。您需要对相同的映射进行操作,以便设置“像素”将确保在检查其邻居时不会对其进行重新排队。

首先,首先将整个HeightMap复制到TerrainMap。

答案 1 :(得分:0)

结构是不可变的,它们的每个修改都会创建一个新对象,就像基本类型一样。我看到一些X ++;和X--;对结构的修改。尝试使IntPoint成为一个类,这样引用就不会让它变得新鲜,看看是否有所改进。