我正在使用此处的代码对2000 x 2000 x 256位图(内存中)进行泛洪填充:http://rosettacode.org/wiki/Bitmap/Flood_fill#C.23
当q Count = 33554432(~33MB)时,队列丢失了内存错误。显然,我有更多的记忆。我还创建了一个IntPoint结构,所以每个点都是2个整数而不是2个双精度。
仅供参考:我怀疑这是否很重要,但我实际上是在内存中填充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++;
}
}
}
一如既往,提前感谢您的帮助!
答案 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成为一个类,这样引用就不会让它变得新鲜,看看是否有所改进。