2012-04-12 86 views
2

我刚碰到一个问题,同时试图为Android设备编写位图操作算法。for循环在Android设备上很慢

我有一个1680x128像素的位图,需要对其应用过滤器。但是这个非常简单的代码片段在我的Android设备上运行了将近15-20秒(带有1Ghz处理器的xperia ray)。

所以我试图找到瓶颈,减少尽可能多的代码行,并最终与循环本身,这几乎同时运行。

for (int j = 0; j < 128; j++) { 
    for (int i = 0; i < 1680; i++) { 
     Double test = Math.random(); 
    } 
} 

这样的设备在没有困难的操作的情况下花费那么多时间在简单的for循环中正常吗?

我对移动设备上的编程非常陌生,所以请原谅,如果这个问题可能是愚蠢的。

更新:现在用一些简单的操作快点吧。

但回到我的主要问题:

public static void filterImage(Bitmap img, FilterStrategy filter) { 
    img.prepareToDraw(); 
    int height = img.getHeight(); 
    int width = img.getWidth(); 
      RGB rgb; 
    for (int j = 0; j < height; j++) { 
     for (int i = 0; i < width; i++) { 
      rgb = new RGB(img.getPixel(i, j)); 
      if (filter.isBlack(rgb)) { 
       img.setPixel(i, j, 0); 
      } else 
       img.setPixel(i, j, 0xffffffff); 
     } 
    } 
    return; 
} 

上面的代码是什么我真的需要在设备上运行得更快。 (几乎立即) 您是否看到其中的优化潜力?

RGB只是一个计算红色,绿色和蓝色值的类,如果所有三个颜色部分都低于100或任何其他指定值,则过滤器会简单地返回true。 img.getPixel(i,j)或setPixel周围的循环需要20秒或更多秒。这是一个如此昂贵的操作吗?

回答

1

首先Stephen C提出了一个很好的论点:尽量避免创建一堆RGB对象。

所有的二,你可以通过一个单一的电话更换您的相对昂贵的呼叫getPixelgetPixels

做出了巨大的改进我做了一些快速测试和管理,以切断运行时间约10%。试试看。这是我使用的代码:

int[] pixels = new int[height * width]; 
img.getPixels(pixels, 0, width, 0, 0, width, height); 

for(int pixel:pixels) { 
    // check the pixel 
} 
+0

好的,我马上试试。谢谢你到目前为止。 – Woyzeck 2012-04-12 12:11:42

+0

这个和其他一些变化加快了算法。感谢您的快速建议:) – Woyzeck 2012-04-12 14:46:40

3

这可能是因为被创建型双太多对象..因此增加堆的大小和装置开始冻结..

一种方法是围绕

double[] arr = new double[128] 
for (int j = 0; j < 128; j++) { 
    for (int i = 0; i < 1680; i++) { 
     arr[i] = Math.random(); 
    } 
} 
+0

双重测试;对于(int i = 0; i <100; i ++) for(int j = 0; j <500; j ++) test = Math.random(); //这不是更快...... – Woyzeck 2012-04-12 10:09:31

+0

@Woyzeck ..你是什么意思..? – ngesh 2012-04-12 10:10:16

+0

对不起,评论现在编辑 – Woyzeck 2012-04-12 10:11:14

1

有一个在一个声明以下为可能会影响性能的随机文档,请尝试自己创建实例而不是使用静态版本,我已经突出显示了以粗体显示的性能免责声明:

返回伪随机double n,其中n> = 0.0 & & n < 1.0。此方法重用Random的单个实例。此方法是线程安全的,因为对Random的访问是同步的,但这会损害可伸缩性。 应用程序可以通过为每个线程分配Random来发现性能优势。

尝试创建自己的随机的,因为你的类的静态字段,以避免同步访问:

private static Random random = new Random(); 

然后按如下方式使用它:

double r = random.nextDouble(); 

也可以考虑使用浮动(random.nextFloat ())如果你不需要双精度。

0

RGB只是一个计算红色,绿色和蓝色值的类,如果所有三个颜色部分都低于100或任何其他指定值,则过滤器会简单地返回true。

一个问题是您正在创建RGB类的height * width实例,只是为了测试单个pizel是否为黑色。将该方法替换为将要测试的像素作为参数的静态方法调用。


更一般地,如果你不知道为什么有些代码段是慢...... 简介它。在这种情况下,分析器会告诉你在RGB构造函数中花费了大量的时间。内存分析器会告诉你大量的RGB对象正在被创建和垃圾收集。

+0

好点,但即使我将所有这些行注释掉,并且只是遍历所有像素以将它们设置为黑色,代码也会持续20秒。怎么来的? – Woyzeck 2012-04-12 11:49:24

+0

您是否像我建议的那样对它进行了配置? – 2012-04-12 12:00:03

+0

我现在在做。 setPixel会导致checkPixelAccess(45%)和其他方法每次运行。 nativeSetPixel调用本身每个setPixel调用只有7%的CPU时间。我现在将尝试使用@sandis代码片断。希望这有助于避免这些无谓的电话。 – Woyzeck 2012-04-12 12:11:56