2012-10-09 147 views
9

我有一個應用程序,索引視頻中出現的前16種顏色。如何將RGB顏色轉換爲最接近的匹配8位顏色?

我試圖寫另一個應用程序,允許用戶選擇一種顏色,然後應用程序找到這種顏色出現在所有視頻。

的問題是,按照視頻我只指數16種顏色,用戶選擇RGB顏色。這種顏色索引的概率非常低,所以幾乎總是我的應用程序沒有返回結果。

我想到了一種方法,我可以使這項工作 - 我可以索引出現在視頻中的顏色,並將它們轉換爲最接近的8位顏色。

然後當用戶選擇RGB顏色時,我可以將用戶選擇轉換爲相同的8位最接近的顏色。

這樣我總是會找到匹配的。

我現在唯一的主要問題是如何將RGB顏色轉換爲最接近的8位顏色?

+0

你在用什麼語言?也許一些圖書館已經做到了。 –

+0

8位顏色可以通過幾種不同的方式完成。它可能是一個顏色表或RRRGGGBB值等的索引。您希望使用哪種8位顏色? – cHao

+0

8位不足以表示任意顏色。 –

回答

0

您是否熟悉Floyd–Steinberg dithering?這用於將高階顏色轉換爲低階顏色,例如, 24位RGB至3位(8色)RGB或將RGB圖像限制爲8位(256色)以進行GIF轉換。

該算法在鏈接的維基百科頁面上描述。

+0

這個想法是轉換單一的顏色。抖動在這個應用中沒有意義。 –

4

您需要做的是將RGB轉換爲HSB(色相飽和度亮度)值。 HSB是3個字節,就像RGB一樣,不同之處在於HSB值可以比RGB更容易地進行比較。

您的下一步是決定「重要性」權重。例如,如果您關心的只是「色彩/色調」而不是飽和度或亮度,那麼您可以丟棄S和B字節並只使用顏色字節。如果是我並且我被約束到8位,我將使用4位顏色信息(16種不同顏色),3位飽和度(8個不同值)和1位亮度信息(亮或暗) 。

本文介紹如何用Java做HSB:

http://java.sys-con.com/node/43559

本文的源代碼中有一個RGB在Java HSB轉換器。

+0

我會用2位飽和度和2位亮度自己去。 –

5

要轉換爲Web安全調色板,你需要每一個R,G,B組分的範圍從0-255轉換爲0-5,並結合他們:

color = (r*6/256)*36 + (g*6/256)*6 + (b*6/256) 
2

一種可能性是簡單地將24位顏色縮放到8位顏色空間。正如cHao提到的,你可以使用RRRGGGBB作爲你的8位數字。然後每個顏色分量可以通過簡單的縮放算法來計算,例如:

byte red = (originalColor.red * 8)/256; 
byte green = (originalColor.green * 8)/256; 
byte blue = (originalColor.blue * 4)/256; 

的8,4,和254是在每個顏色分量的可能值的數目。在原來的24位顏色中,紅色,綠色和藍色都可以有256個可能的值,所以這是縮放等式的除數。在示例8位顏色中,紅色和綠色每個都是3位(8個可能值),藍色是2位(4個可能值)。

後,你要把這三個組件,你可以用一些簡單的移位運算將它們組合起來:

byte eightBitColor = (red << 5) | (green << 2) | blue; 

然後,你可以簡單地比較這8位色彩。他們大幅降低的分辨率可能會對您有所幫助。或者,你可以做類似Tyler建議的事情,並先轉換成HSB或HSV,然後只比較色調(取決於你是否需要亮度和飽和度信息)。根據你的目標,這可能實際上是一個更理想的解決方案。

編輯:修改縮放算法來修復由Mark Ransom指出的缺點。

+0

對於只有8位的顏色範圍,忽略位邊界並使用非2的冪範圍更有意義。您的答案有8種可能的紅色,8種可能的綠色,但只有4種可能的藍色;更典型的是6,6,6(如我的答案)或6,7,6。此外,您的縮放比例稍微偏低,因爲只有255的輸入會提供最大的輸出,而這些值將被不足表示。 –

+0

的確如此。我真的只是想詳細闡述cHao的評論。 我編輯了我的答案來解決縮放問題。 –

+0

JSBin:http://jsbin.com/voqacamema/3/ –

0

,如果你想 24 BPP圖像轉換爲8 BPP圖像試試這個算法:

for y = 0 to ImageHeight - 1 
    for x = 0 to ImageWidth - 1 
     GetPixel(x,y,red,grn,blu) 
     {read RGB data from 24bpp file} 
     d0 = red^2 + grn^2 + blu^2 
     ColorIndex = 0 
     for cl = 0 to 255 
     GetPaletteData(p_red,p_gre,p_blu) 
     {read RGB data from 8bpp palette} 
     d = (red - p_red)^2 + (grn - p_grn)^2 + (blu - p_blu)^2 
     if d0 >= d then 
      ColorIndex = cl 
      d0 = d 
     end if 
     next cl 
     {use ColorIndex to create your 8bpp file} 
    next x 
    next y 

這個步驟之前,請閱讀更多關於維基百科或其他來源8bpp的文件。

祝你好運!