2014-09-01 67 views
1

我完成了一部分代碼,但在某些比較中,最接近的值是不正確的。 實施例:使用調色板中的調色板數組找到最接近的RGB值C

正確:

Rgb value | Value from array 
0xFFFFFD = 0xFFFFFF 

不正確: 固定碼

Rgb value | Value from array 
0xF4F939 = 0xFF0000 (should be 0xFFFF00) 

控制檯輸出:(正確)

C:\Users\honguito\Desktop\Bat\Game_Batch_Files\24_to_8_bitmap>24_to_8_bit_palett 
e 
The closest color of 0xFFFFFD is: '0xFFFFFF' 

C:\Users\honguito\Desktop\Bat\Game_Batch_Files\24_to_8_bitmap> 

控制檯輸出:(錯誤)

C:\Users\honguito\Desktop\Bat\Game_Batch_Files\24_to_8_bitmap>24_to_8_bit_palett 
e 
The closest color of 0xF4F939 is: '0xFF0000' 

C:\Users\honguito\Desktop\Bat\Game_Batch_Files\24_to_8_bitmap> 

那些RGB顏色代碼在陣列中被列出:

int data[] = { 
    0x000000, 0x800000, 0x008000, 0x808000, 0x000080, 0x800080, 0x008080, 
    0xC0C0C0, 0xC0DCC0, 0xA6CAF0, 0x402000, 0x602000, 0x802000, 0xA02000, 
    0xC02000, 0xE02000, 0x004000, 0x204000, 0x404000, 0x604000, 0x804000, 
    0xA04000, 0xC04000, 0xE04000, 0x006000, 0x206000, 0x406000, 0x606000, 
    0x806000, 0xA06000, 0xC06000, 0xE06000, 0x008000, 0x208000, 0x408000, 
    0x608000, 0x808000, 0xA08000, 0xC08000, 0xE08000, 0x00A000, 0x20A000, 
    0x40A000, 0x60A000, 0x80A000, 0xA0A000, 0xC0A000, 0xE0A000, 0x00C000, 
    0x20C000, 0x40C000, 0x60C000, 0x80C000, 0xA0C000, 0xC0C000, 0xE0C000, 
    0x00E000, 0x20E000, 0x40E000, 0x60E000, 0x80E000, 0xA0E000, 0xC0E000, 
    0xE0E000, 0x000040, 0x200040, 0x400040, 0x600040, 0x800040, 0xA00040, 
    0xC00040, 0xE00040, 0x002040, 0x202040, 0x402040, 0x602040, 0x802040, 
    0xA02040, 0xC02040, 0xE02040, 0x004040, 0x204040, 0x404040, 0x604040, 
    0x804040, 0xA04040, 0xC04040, 0xE04040, 0x006040, 0x206040, 0x406040, 
    0x606040, 0x806040, 0xA06040, 0xC06040, 0xE06040, 0x008040, 0x208040, 
    0x408040, 0x608040, 0x808040, 0xA08040, 0xC08040, 0xE08040, 0x00A040, 
    0x20A040, 0x40A040, 0x60A040, 0x80A040, 0xA0A040, 0xC0A040, 0xE0A040, 
    0x00C040, 0x20C040, 0x40C040, 0x60C040, 0x80C040, 0xA0C040, 0xC0C040, 
    0xE0C040, 0x00E040, 0x20E040, 0x40E040, 0x60E040, 0x80E040, 0xA0E040, 
    0xC0E040, 0xE0E040, 0x000080, 0x200080, 0x400080, 0x600080, 0x800080, 
    0xA00080, 0xC00080, 0xE00080, 0x002080, 0x202080, 0x402080, 0x602080, 
    0x802080, 0xA02080, 0xC02080, 0xE02080, 0x004080, 0x204080, 0x404080, 
    0x604080, 0x804080, 0xA04080, 0xC04080, 0xE04080, 0x006080, 0x206080, 
    0x406080, 0x606080, 0x806080, 0xA06080, 0xC06080, 0xE06080, 0x008080, 
    0x208080, 0x408080, 0x608080, 0x808080, 0xA08080, 0xC08080, 0xE08080, 
    0x00A080, 0x20A080, 0x40A080, 0x60A080, 0x80A080, 0xA0A080, 0xC0A080, 
    0xE0A080, 0x00C080, 0x20C080, 0x40C080, 0x60C080, 0x80C080, 0xA0C080, 
    0xC0C080, 0xE0C080, 0x00E080, 0x20E080, 0x40E080, 0x60E080, 0x80E080, 
    0xA0E080, 0xC0E080, 0xE0E080, 0x0000C0, 0x2000C0, 0x4000C0, 0x6000C0, 
    0x8000C0, 0xA000C0, 0xC000C0, 0xE000C0, 0x0020C0, 0x2020C0, 0x4020C0, 
    0x6020C0, 0x8020C0, 0xA020C0, 0xC020C0, 0xE020C0, 0x0040C0, 0x2040C0, 
    0x4040C0, 0x6040C0, 0x8040C0, 0xA040C0, 0xC040C0, 0xE040C0, 0x0060C0, 
    0x2060C0, 0x4060C0, 0x6060C0, 0x8060C0, 0xA060C0, 0xC060C0, 0xE060C0, 
    0x0080C0, 0x2080C0, 0x4080C0, 0x6080C0, 0x8080C0, 0xA080C0, 0xC080C0, 
    0xE080C0, 0x00A0C0, 0x20A0C0, 0x40A0C0, 0x60A0C0, 0x80A0C0, 0xA0A0C0, 
    0xC0A0C0, 0xE0A0C0, 0x00C0C0, 0x20C0C0, 0x40C0C0, 0x60C0C0, 0x80C0C0, 
    0xA0C0C0, 0xFFFBF0, 0xA0A0A4, 0x808080, 0xFF0000, 0x00FF00, 0xFFFF00, 
    0x0000FF, 0xFF00FF, 0x00FFFF, 0xFFFFFF 
}; 

然後得到最接近的數字我做:

nearest = findKey(data, pcolor); 

這是完整的代碼:

#include <stdio.h> 

int main() { 

    //int pcolor = 0xF4F939; 
    int pcolor = 0xFFFFFD; 
    //int pcolor = 0x700000; 
    //int pcolor = 0x21A0C0; 
    int cmp[256]; 
    int cmp2[256]; 
    int data[] = { 
     0x000000, 0x800000, 0x008000, 0x808000, 0x000080, 0x800080, 0x008080, 
     0xC0C0C0, 0xC0DCC0, 0xA6CAF0, 0x402000, 0x602000, 0x802000, 0xA02000, 
     0xC02000, 0xE02000, 0x004000, 0x204000, 0x404000, 0x604000, 0x804000, 
     0xA04000, 0xC04000, 0xE04000, 0x006000, 0x206000, 0x406000, 0x606000, 
     0x806000, 0xA06000, 0xC06000, 0xE06000, 0x008000, 0x208000, 0x408000, 
     0x608000, 0x808000, 0xA08000, 0xC08000, 0xE08000, 0x00A000, 0x20A000, 
     0x40A000, 0x60A000, 0x80A000, 0xA0A000, 0xC0A000, 0xE0A000, 0x00C000, 
     0x20C000, 0x40C000, 0x60C000, 0x80C000, 0xA0C000, 0xC0C000, 0xE0C000, 
     0x00E000, 0x20E000, 0x40E000, 0x60E000, 0x80E000, 0xA0E000, 0xC0E000, 
     0xE0E000, 0x000040, 0x200040, 0x400040, 0x600040, 0x800040, 0xA00040, 
     0xC00040, 0xE00040, 0x002040, 0x202040, 0x402040, 0x602040, 0x802040, 
     0xA02040, 0xC02040, 0xE02040, 0x004040, 0x204040, 0x404040, 0x604040, 
     0x804040, 0xA04040, 0xC04040, 0xE04040, 0x006040, 0x206040, 0x406040, 
     0x606040, 0x806040, 0xA06040, 0xC06040, 0xE06040, 0x008040, 0x208040, 
     0x408040, 0x608040, 0x808040, 0xA08040, 0xC08040, 0xE08040, 0x00A040, 
     0x20A040, 0x40A040, 0x60A040, 0x80A040, 0xA0A040, 0xC0A040, 0xE0A040, 
     0x00C040, 0x20C040, 0x40C040, 0x60C040, 0x80C040, 0xA0C040, 0xC0C040, 
     0xE0C040, 0x00E040, 0x20E040, 0x40E040, 0x60E040, 0x80E040, 0xA0E040, 
     0xC0E040, 0xE0E040, 0x000080, 0x200080, 0x400080, 0x600080, 0x800080, 
     0xA00080, 0xC00080, 0xE00080, 0x002080, 0x202080, 0x402080, 0x602080, 
     0x802080, 0xA02080, 0xC02080, 0xE02080, 0x004080, 0x204080, 0x404080, 
     0x604080, 0x804080, 0xA04080, 0xC04080, 0xE04080, 0x006080, 0x206080, 
     0x406080, 0x606080, 0x806080, 0xA06080, 0xC06080, 0xE06080, 0x008080, 
     0x208080, 0x408080, 0x608080, 0x808080, 0xA08080, 0xC08080, 0xE08080, 
     0x00A080, 0x20A080, 0x40A080, 0x60A080, 0x80A080, 0xA0A080, 0xC0A080, 
     0xE0A080, 0x00C080, 0x20C080, 0x40C080, 0x60C080, 0x80C080, 0xA0C080, 
     0xC0C080, 0xE0C080, 0x00E080, 0x20E080, 0x40E080, 0x60E080, 0x80E080, 
     0xA0E080, 0xC0E080, 0xE0E080, 0x0000C0, 0x2000C0, 0x4000C0, 0x6000C0, 
     0x8000C0, 0xA000C0, 0xC000C0, 0xE000C0, 0x0020C0, 0x2020C0, 0x4020C0, 
     0x6020C0, 0x8020C0, 0xA020C0, 0xC020C0, 0xE020C0, 0x0040C0, 0x2040C0, 
     0x4040C0, 0x6040C0, 0x8040C0, 0xA040C0, 0xC040C0, 0xE040C0, 0x0060C0, 
     0x2060C0, 0x4060C0, 0x6060C0, 0x8060C0, 0xA060C0, 0xC060C0, 0xE060C0, 
     0x0080C0, 0x2080C0, 0x4080C0, 0x6080C0, 0x8080C0, 0xA080C0, 0xC080C0, 
     0xE080C0, 0x00A0C0, 0x20A0C0, 0x40A0C0, 0x60A0C0, 0x80A0C0, 0xA0A0C0, 
     0xC0A0C0, 0xE0A0C0, 0x00C0C0, 0x20C0C0, 0x40C0C0, 0x60C0C0, 0x80C0C0, 
     0xA0C0C0, 0xFFFBF0, 0xA0A0A4, 0x808080, 0xFF0000, 0x00FF00, 0xFFFF00, 
     0x0000FF, 0xFF00FF, 0x00FFFF, 0xFFFFFF 
    }; 

    int nearIndex,nearest, result; 

    nearest = findKey(data, pcolor);  
    printf("The closest color of 0x%X is: '0x%X'\n", pcolor, nearest); 
    //system("pause"); 
} 


int findKey(int Array1[], int key){ 
    int diff = abs(key - Array1[0]); 
    int Num1 = 0; 
    int Num2 = 0; 
    for (int a = 0; a < 256; a++) { 
      if (diff > abs(key - Array1[a])) { 
      diff = abs(key - Array1[a]); 
      Num1 = Array1[a]; 
     } 
    } 
    return Num1; 
    } 

有一些未使用的變量和舊代碼。

任何想法?

+0

實際上,根據您的代碼所用的定義「接近度」(絕對差),代碼是正確的:0xFF0000和0x21A0C0之間的差值小於0xFFF000和相同值之間的差值。 – cnicutar 2014-09-01 20:49:34

+0

哦,我錯了,在第二個代碼塊中,它是0xF4F939,而不是0x21A0C0。對不起! – Honguito98 2014-09-01 21:06:34

+0

這仍然是一樣的情況。用計算器做一個減法運算 – cnicutar 2014-09-01 21:11:35

回答

2

要找到「光學」最接近的顏色,您必須估算您正在比較的兩種顏色的顏色分量之間的差異。

爲了做到這一點,你必須將24位值分成8位顏色分量r,g,b。

然後您比較組件。

一個天真的方法來做到這一點只是總結各個組件差異的絕對值。

更準確的公式可以發現谷歌搜索,我猜。

// two colors to compare 

int c1; 
int c2; 

// split c1 and c2 into their respective color components 

r1 = c1/0x010000; 
g1 = (c1 % 0x010000)/0x00100; 
b1 = c1 % 0x000100; 

r2 = c2/0x010000; 
g2 = (c2 % 0x010000)/0x00100; 
b2 = c2 % 0x000100; 

// color "distance" 

diff = abs(r1 - r2) + abs(g1 - g2) + abs (b1 - b2); 
+0

最初,我試圖在pcolor和data []數組之間獲得RGB複合差分。但我從來沒有嘗試將RGB十六進制代碼分成3個變量。 P.S:還有一種更有效的方法是使用邏輯移位來分割RGB十六進制代碼。第2頁:謝謝你的幫助! – Honguito98 2014-09-02 22:57:03

+0

當然,有更有效的方法來分割顏色;我的代碼只是爲了給出這個想法。也可能有更精確的公式來比較基於組件值的顏色。但是,這只是爲了給出這個想法,即:「首先將顏色分解成組件」。不客氣地歡迎 – Paolo 2014-09-04 06:14:48

+0

As [John Hascall](http://stackoverflow.com/a/25715571/2564301)在他的筆記答案,距離最好測量歐幾里得。 – usr2564301 2014-09-15 00:36:32

1

我認爲,使用3 d距離公式是計算的「最近」色(因爲你只關心比較,你可以跳過sqrt()末)一個更準確的方法。

dist_r = abs(r1 - r2); 
dist_g = abs(g1 - g2); 
dist_b = abs(b1 - b2); 
dist_3d_sqd = (dist_r * dist_r) + (dist_g * dist_g) + (dist_b * dist_b 

其實你可以跳過abs()電話太多,但把它們放在使它更清晰,也許?