2011-11-03 77 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算法會有所幫助。