0

我正在编写一个逐像素处理图像的Android应用程序。为了读取和设置像素,我使用了两个嵌套循环。

这个过程非常耗时。即使我删除循环中的指令,在 8 兆像素图像上运行也需要大约一分钟。

为什么需要这么长时间?还有其他获取和设置像素的方法吗?

    long mn = img_w*img_h;
    long o = 0;
    for(int i =0;i<img_w;i++) {
        for(int j=0;j<img_h;j++) {

                System.out.println(mn-o);

        o++;

        }
    }

此代码模拟处理图像,并且此代码需要很长时间

logcat(部分):

    02-12 19:01:40.815: I/System.out(332): 4999.0
02-12 19:01:40.815: I/System.out(332): 4998.0
02-12 19:01:40.815: I/System.out(332): 4997.0
02-12 19:01:40.825: I/System.out(332): 4996.0
02-12 19:01:40.825: I/System.out(332): 4995.0
02-12 19:01:40.825: I/System.out(332): 4994.0
02-12 19:01:40.825: I/System.out(332): 4993.0
02-12 19:01:40.825: I/System.out(332): 4992.0
02-12 19:01:40.825: I/System.out(332): 4991.0
02-12 19:01:40.825: I/System.out(332): 4990.0
02-12 19:01:40.835: I/System.out(332): 4989.0
02-12 19:01:40.835: I/System.out(332): 4988.0
02-12 19:01:40.835: I/System.out(332): 4987.0
02-12 19:01:40.835: I/System.out(332): 4986.0
02-12 19:01:40.845: I/System.out(332): 4985.0
02-12 19:01:40.845: I/System.out(332): 4984.0
02-12 19:01:40.845: I/System.out(332): 4983.0
02-12 19:01:40.845: I/System.out(332): 4982.0
02-12 19:01:40.845: I/System.out(332): 4981.0
02-12 19:01:40.845: I/System.out(332): 4980.0
02-12 19:01:40.845: I/System.out(332): 4979.0
02-12 19:01:40.845: I/System.out(332): 4978.0
02-12 19:01:40.855: I/System.out(332): 4977.0
02-12 19:01:40.855: I/System.out(332): 4976.0
02-12 19:01:40.855: I/System.out(332): 4975.0
02-12 19:01:40.855: I/System.out(332): 4974.0
02-12 19:01:40.855: I/System.out(332): 4973.0
02-12 19:01:40.865: I/System.out(332): 4972.0
4

2 回答 2

1

您安排循环的方式对缓存非常不友好。使内环越过宽度,外环越过高度。

于 2013-02-12T18:43:37.840 回答
0

我认为您不能以这种方式在 Java 中解决您的问题。执行 Java 语句(尤其是方法调用)会产生开销,并且执行 800 万次——即使指令几乎什么都不做,比如设置一个值——总是很慢。

标准答案是在 C++ 中实现此函数,该函数由 Java 虚拟机编译而不是解释,因此应该更快。对于实时应用程序来说,它可能仍然不够快;你仍然在做 800 万次,只是每次都少了。

在整个 8 Mb 像素缓冲区中用 Java 进行 peek 和 poke 操作永远不会很快。然而,Java 的设计者意识到了这个问题,这就是为什么他们提供扩展的 2D 图形 API 来经常消除执行一百万次的 for 循环的需要。我建议仔细查看 2D API 库,该库旨在设置和读取位图中的位。根据您真正想要做的事情,可能会有更快的方法。您可以设置一个具有透明背景的位图,并将您的更改写入该位图,并将该位图写入前一个图像的顶部。当您在位图之上编写位图时,您可以设置一个 Paint 类来处理印象深刻的图像(例如,通过对其应用可变透明度)。Android 2d Graphics API 还支持“Porter-Duff” compositing 提供允许以新颖方式组合图像的调用。所有这些基本上都是在硬件中执行的,因此速度非常快。

在不知道您(确切地)要做什么的情况下,我无法告诉您如何更有效地执行此操作,但是在很多情况下,实现方式比您使用的蛮力方法要有效得多。如果没有,而你想要这个实时,我怀疑你被塞满了。

于 2013-02-13T05:43:09.120 回答