我在尝试为Android设备编写位图操作算法时遇到了一个问题。
我有一个1680x128像素的位图,需要对它应用滤镜。但这个非常简单的代码实际上花了将近15-20秒在我的Android设备上运行(带有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秒或更长时间。这是一项如此昂贵的操作吗?
答案 0 :(得分:3)
可能是因为创建了太多Double类型的对象..因此它增加了堆大小并且设备开始冻结..
方法是
double[] arr = new double[128]
for (int j = 0; j < 128; j++) {
for (int i = 0; i < 1680; i++) {
arr[i] = Math.random();
}
}
答案 1 :(得分:1)
下面的文档中有一个免责声明可能会影响性能,尝试自己创建一个实例而不是使用静态版本,我已经用粗体突出显示了性能免责声明:
返回伪随机双n,其中n> = 0.0&amp;&amp; n&lt; 1.0。此方法重用Random的单个实例。此方法是线程安全的,因为对Random的访问是同步的,但这会损害可伸缩性。 应用程序可以通过为每个线程分配一个Random来获得性能优势。
尝试创建自己的随机数作为类的静态字段,以避免同步访问:
private static Random random = new Random();
然后按如下方式使用:
double r = random.nextDouble();
如果你不需要双精度,也可以考虑使用float(random.nextFloat())。
答案 2 :(得分:1)
首先,Stephen C提出了一个很好的论点:尽量避免创建一堆RGB对象。
其次,只需拨打一次getPixels
getPixel
,从而取得巨大进步。
我进行了一些快速测试,并设法将运行时间减少到大约10%。试试看。这是我使用的代码:
int[] pixels = new int[height * width];
img.getPixels(pixels, 0, width, 0, 0, width, height);
for(int pixel:pixels) {
// check the pixel
}
答案 3 :(得分:0)
RGB只是一个计算红色,绿色和蓝色值的类,如果所有三个颜色部分都低于100或任何其他指定值,则过滤器只返回true。
一个问题是您正在创建RGB类的height * width
个实例,只是为了测试单个pizel是否为黑色。用静态方法调用替换该方法,该方法将要测试的像素作为参数。
更一般地说,如果你不知道为什么某段代码很慢...... 描述它。在这种情况下,探查器会告诉您RGB构造函数花费了大量时间。内存分析器会告诉您正在创建大量RGB对象并收集垃圾。