3

我在尝试为 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 秒或更长时间。这是一项如此昂贵的手术吗?

4

4 回答 4

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();
    }
}
于 2012-04-12T10:07:43.903 回答
2

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

getPixel其次,您可以通过一次调用来替换相对昂贵的调用getPixels

我做了一些快速测试,并设法将运行时间减少到 10% 左右。试试看。这是我使用的代码:

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

for(int pixel:pixels) {
    // check the pixel
}
于 2012-04-12T11:56:22.540 回答
1

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

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

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

private static Random random = new Random();

然后按如下方式使用它:

double r = random.nextDouble();

如果您不需要双精度,还可以考虑使用 float (random.nextFloat())。

于 2012-04-12T10:14:41.370 回答
0

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

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


更一般地说,如果您不知道为什么某些代码很慢……请分析一下。在这种情况下,分析器会告诉您在 RGB 构造函数中花费了大量时间。内存分析器会告诉您正在创建大量 RGB 对象并进行垃圾收集。

于 2012-04-12T11:09:37.493 回答