2011-11-03 49 views
1

我正在使用Java。
我正在开发一个绘图程序,“Paint Can”工具使用Flood Fill算法,但它太昂贵了。算法,洪水填充(深度优先搜索)

下面是代码:

private int[] dx = { -1, 0, 1, 0 }; 
private int[] dy = { 0, 1, 0, -1 }; 

public void floodFill(int x, int y, Color target_color, Color replacement_color) { 
    Stack<Integer[]> stack = new Stack<Integer[]>(); 
    if (imageBuffer.getRGB(x, y) == replacement_color.getRGB()) 
     return; 
    stack.push(new Integer[] { x, y }); 
    while (!stack.isEmpty()) { 
     Integer[] aux = stack.peek(); 
     imageBuffer.setRGB(aux[0], aux[1], replacement_color.getRGB()); 
     stack.pop(); 
     for (int i = 0; i < 4; i++) { 
      if (imageBuffer.getRGB(aux[0] + dx[i], aux[1] + dy[i]) == target_color.getRGB()) 
       stack.push(new Integer[] { aux[0] + dx[i], aux[1] + dy[i] }); 
     } 

    } 
} 

有人可以帮我做这个更有效率?

需要(对于1020x700像素图像)大约1200ms执行。

+0

我认为最主要的是你需要一个更好的算法。 http://en.wikipedia.org/wiki/Flood_fill是一个很好的资源。有一些微观优化你可以做到(例如'replacement_color.getRGB()'每次评估,因为它'target_color.getRGB()',但我不认为这会有很大的不同。 –

回答

1

使用队列算法的基本思想,你可以阅读here(+ example)。

你也许可以找到其他的优化和实现,但我发现这一个Queue-Linear Flood Fill。你应该自己做这个工作。

1

一个简单的(也许很小的)改进就是用ArrayDeque替换堆栈。

这将允许您指定初始容量并使您的代码更新。当floodFill区域包含许多像素时,需要多次扩展叠加叠加的向量。这是浪费 - 但不是所有昂贵的

0

我曾试图在一年前实施洪泛算法很长一段时间。我第一次尝试了我自己的解决方案,当他们没有足够的性能时,我去了互联网,发现this implementation

QuickFill(实际算法从页面中途开始)算法效果很好。它会在半秒钟内填满我的机器人里程碑的屏幕(480x854)。使用较新的硬件(甚至桌面硬件)可能会比这更快。当然,你必须将它移植到Java,但它不应该太困难,特别是如果我能做到的话!

0

我想说你有很多的内存分配正在进行。您为每个像素分配一个新的Integer[]。我可能会用两堆原语(比如trove4j中的那些数组列表)处理xy,或者至少用int[]替换Integer[]

如果这还不够,也许scanline算法会有所帮助。