2009-11-28 111 views
1

最近我一直想在內存中表示未壓縮的位圖。然而,我不確定如何正確實現的一件事是二進制透明。例如,我在開始時是這樣的:如何表示二進制透明度?

struct RGBPixel { 
uint8_t red; 
uint8_t green; 
uint8_t blue; 
}; 

struct bitmap { 
struct RGBPixel *data; 
size_t width; 
size_t height; 
size_t bytesPerPixel; 
size_t bytewidth; 
/* etc. */ 
}; 

我想最簡單的方法是這樣的:

struct RGBPixel { 
uint8_t red; 
uint8_t green; 
uint8_t blue; 
bool transparent; 
}; 

但似乎有點浪費(你不妨添加一個完整的alpha通道) 。我能想到的唯一的另一種可能性是保留其中一種顏色是透明的,但是然後你失去了顯示該顏色的能力。有沒有一個標準的方法來做到這一點?

常見格式(GIF,8位PNG等)如何表示?

回答

1

有16M的顏色,指定其中一個透明不會是一個大的困難。除非你的圖像是1600萬像素,否則你可以確定它甚至不使用所有的16M色彩,只需選擇一個不使用的圖像並將其設置爲透明色。如果您確實有一張使用全部圖像的巨大圖像,請選擇最少使用的圖像並將其更改爲相鄰的顏色,以免它們被使用。

正如您所指出的那樣,試圖用像素RGB數據來存儲每像素一位是沒有效率的。您應該將所有RGB像素存儲在一個指針中,然後在另一個指針中存儲相同H和V尺寸的位圖,或者可以進行色度鍵控。如上所述,您可以將數據分別存儲在R,G,B和透明度位圖中,但繪製時通常效率很低。

+0

」只是選擇一個不使用的,並使其成爲透明色。「但我該如何挑選這種顏色?在圖像中循環並繼續猜測顏色,直到找到一個未被使用的圖像? – Sam 2009-11-28 18:20:03

+0

從您認爲不會使用的顏色開始。循環使用,如果使用它,記住你所在的像素圖的偏移量,稍微改變顏色(可能增加B值,適當地從G滾動到R),然後循環到像素圖的末尾,然後開始在一開始,如果你沒有找到這種顏色,那就是它。否則,重複。 爲了獲得更好的轉角效果,請選擇您認爲在開始時不會使用的256種顏色並同時進行搜索。找到所有的機會都很低,在4MP圖像中,它是1/4^256或約1e25。 – 2009-11-28 23:06:39

1

Gif使用透明的指定顏色。 (例如:假設0xFFFF00是透明的,因此具有此顏色的所有像素都將顯示爲透明。)此顏色無法在此圖像中使用。
Png有一個alpha通道,這意味着另一個int代表像素的alpha值。 (例如:0 =完全透明,255 =不透明,128 =半透明)

+0

它使用哪種顏色? – Sam 2009-11-28 15:10:16

+1

Gif使用索引顏色,而不是直接顏色。因此,每個像素都被編碼爲256種不同顏色之一,這是RGB顏色查找表的索引。如果你想要透明度,只需將圖像縮小到255種顏色,然後使用剩餘的索引來指示透明度。 – 2009-11-28 16:44:07

+0

那對@南方好客,我只想展示2種方式來定義透明的某些像素。 – TheHippo 2009-11-28 17:28:20

0

通常有第四個Alpha通道來表示透明度。

即代替RBG,你可以有RGBA。

0

二元透明度也稱爲色度鍵控。您指定一種顏色作爲透明顏色,並在繪圖功能中繪製一個像素,如果其顏色不是色度鍵(指定透明顏色)。

當您執行多級透明度(如陰影)時,將使用每像素alpha。

0

你可以存儲在單獨的存儲器中的透明性,或甚至單獨存儲每個信道,例如:

struct bitmap { 
uint8_t *red; 
uint8_t *green; 
uint8_t *blue; 
uint8_t *transparency; 
// or packed: uint8_t *RGB, *transparency; 
size_t width; 
size_t height; 
}; 

然後分配width*height/8字節的透明度信道,並假定每個顏色通道8位可以訪問的位像這樣:

bool get_transparency(struct bitmap* bmp, size_t x, size_t y) { 
    size_t idx = y * bmp->width + x; 
    size_t tidx = idx >> 3; // = idx/8 
    uint8_t t8 = (uint8_t)(idx & 7); // = idx % 8 
    uint8_t mask = 1 << t8; 
    return (bmp->transparency[tidx] & mask) != 0; 
} 

請注意,訪問位可以優化,這只是一個例子。

另一種解決方案:你可以滑動位顏色通道中的一個的,並定義你的結構是這樣的:

struct RGBPixel { 
uint8_t red : 7; 
uint8_t transparency : 1; 
uint8_t green; 
uint8_g blue; 
}; 

存儲或讀取紅色通道時,必須相應地擴大,例如red = (uint8_t)(((uint16_t)pix->red * 8)/7);