我正在编写一个Android应用程序,必须根据接收到的事件绘制加载的位图图像的确定部分。
假设我有一辆汽车,它分为许多部分:门、窗、轮子等。每次事件(从网络接收)到达时,我需要用事件数据指定的颜色更改该特定部分的颜色。实现这一目标的最佳技术是什么?
我首先想到的是FloodFill,正如许多线程所建议的那样,但是考虑到消息的接收速度非常快(每秒几个),我担心它会拖累性能,因为它似乎是非常消耗CPU的算法。
我也考虑过同一张图片的多个部分,每个部分都有不同的颜色,并在正确的时间显示正确的部分,但是汽车至少有10个不同的部分,每个部分可以被涂上4-6种颜色,所以我最终会得到几十个图像,这将是不切实际的,更不用说浪费内存了。
那么,有没有其他的方法呢?
发布于 2016-06-18 15:16:00
执行此操作的最快方法是使用着色器。为此,你需要使用OpenGL ES 2(有些Android只支持ES 1)。您需要一个与要更改的图像大小相同的临时位图。将其设置为目标。在着色器中,从采样器中检索绑定到要更改的图像的像素。如果它在您想要更改的颜色的小公差内,请将gl_FragColor设置为新颜色,否则只需将gl_FragColor设置为您从采样器中检索到的颜色。您需要将所需的颜色和新颜色作为al_set_shader_float_vector
的vec4s传递到着色器中。最快的方法是保留2个位图,并在它们之间交换,作为每次颜色变化时使用的“主位图”。
如果您不能使用着色器,那么您将不得不锁定位图并替换颜色。使用al_lock_bitmap
锁定它,然后可以使用al_get_pixel
和al_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,但它的工作原理与short相同),则位模式将为AAAAAAAABBBBBBBBGGGGGGGGRRRRRRRR
。然而,当你一次读取一个字节时,大多数机器都是小端的,所以这意味着小端在前面。这就是为什么在我的示例代码中p是红色的。8888部分告诉每个组件有多少位。
https://stackoverflow.com/questions/18062524
复制相似问题