2013-08-05 75 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部分告訴每個組件有多少位。