2013-08-05 76 views
0

我正在编写一个Android应用程序,该应用程序必须根据收到的事件绘制已加载的位图图像的已确定部分。从位图图像的特定部分更改颜色

我需要绘制(或更改当前颜色)的位图图像的一个部分,而不会更改图像的其余部分。

比方说,我有一辆车,它被很多部分分开:门,窗户,车轮等。 每当一个事件(从网络收到)到达时,我需要改变该特定部分的颜色由事件数据指定的颜色。 什么是最好的技术来实现这一目标?

我首先想到了FloodFill,正如SO中的许多线程所建议的那样,但考虑到收到的消息速度很快(每秒几次),我担心它会降低性能,因为它似乎是CPU密集型算法。

我也考虑过有相同图像的多个部分,每个部分用不同的颜色着色,并在正确的时间显示正确的一部分,但汽车至少有10个不同的部分,每个部分可以涂上4- 6种颜色,所以我最终会得到几十张图片,这对于处理来说是不切实际的,更不用说浪费了记忆。

那么,有没有其他的方法?

+0

你不能拥有它 - 如果你想要盲目的速度,他们应该被预先渲染。我没有看到任何真正的问题。在不了解实际“部分”定义等的情况下,很难提供有意义的速度比较。 –

+0

零件本身并不复杂 - 它是一个程式化的绘图 - 我相信它们会很快吸引。这是令我担心的部件x颜色组合的数量。我也曾想过为每个部分分开透明的图像,用适当的颜色绘制它们并绘制现有的完整图像,但不知道如何精确定位在正确的坐标上。 – mirso

回答

0

最快的方法是使用着色器。您需要使用OpenGL ES 2(有些Android仅支持ES 1)。您需要一个与您想要更改的图像大小相同的临时位图。将其设置为目标。在着色器中,从采样器中检索与要更改的图像绑定的像素。如果它处于要更改颜色的小容差范围内,请将gl_FragColor设置为新颜色,否则只需将gl_FragColor设置为从采样器中检索的颜色即可。您需要将所需的颜色和新颜色传递到着色器,作为与al_set_shader_float_vector的vec4s。最快的方法是保存2个位图并在它们之间进行交换,作为每次颜色变化时使用的“主要位置”。

如果你不能使用着色器,那么你将不得不锁定位图并替换颜色。使用al_lock_bitmap锁定它,然后您可以使用al_get_pixelal_put_pixel更改颜色。然后当你完成后al_unlock_bitmap。您还可以避免使用al_get_pixel/al_put_pixel并手动访问内存,速度会更快。如果你与当时的格式ALLEGRO_PIXEL_FORMAT_ABGR_8888_LE锁定位的内存布局,像这样:

int w = al_get_bitmap_width(bitmap); int h = al_get_bitmap_height(bitmap); for (int y = 0; y < h; y++) { unsigned char *p = locked_region->data + locked_region->pitch * y; for (int x = 0; x < w; x++) { unsigned char r = p[0]; unsigned char g = p[1]; unsigned char b = p[2]; unsigned char a = p[3]; /* change r, g, b, a here if they match */ p[0] = r; p[1] = g; p[2] = b; p[3] = a; p += 4; } }

它的建议,你锁在其创建的格式的图像也就是说,挑容易的喜欢。我提到了一个,否则循环的内部变得更加复杂。像素格式的ABGR_8888部分描述了数据的布局。 ABGR讲述组件的顺序。如果您要将像素读入单个存储单元(在这种情况下为int,但与短一样),则位模式将为AAAAAAAABBBBBBBBGGGGGGGGRRRRRRRR。但是,当你一次读取一个字节时,大多数机器都是小端,所以这意味着小端先出现。这就是为什么我的示例代码p [0]是红色的。 8888部分告诉每个组件有多少位。