最快的方法是使用着色器。为此,您需要使用 OpenGL ES 2(某些 Android 仅支持 ES 1)。您需要一个与要更改的图像大小相同的临时位图。将其设置为目标。在着色器中,从采样器中检索一个像素,该像素绑定到要更改的图像。如果它在您要更改的颜色的小公差范围内,请将 gl_FragColor 设置为新颜色,否则只需将 gl_FragColor 设置为您从采样器中检索到的颜色。您需要将所需颜色和新颜色作为 vec4s 和al_set_shader_float_vector
. 最快的方法是保留 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[0] 是红色的。8888 部分说明每个组件有多少位。