RGB888轉RGB565

 

今天在REVIEW代碼的時候,發現了這樣一個宏定義:

#define COLOR_TO_MTK_COLOR_SIMUL(color) ((((color) >> 19) & 0x1f) << 11) \
                                            |((((color) >> 10) & 0x3f) << 5) \
                                            |(((color) >> 3) & 0x1f)

大家知道這個宏是用來幹什麼的嗎?

仔細分析後,原來就是實現了RGB888到RGB565的轉換,查閱相關資料後,發現網絡上有一篇牛人寫的東東,在此和大家分享。

講一下量化壓縮與量化補償吧

  在進行色彩格式轉換的時候,經常會遇到色彩量化位數的改變,比如說從 24bit RGB888 到 16bit RGB565 的色彩轉換。所謂量化壓縮與量化補償都是我個人所提出的概念,現說明如下。

  量化壓縮,舉例:

  24bit RGB888 -> 16bit RGB565 的轉換

  24ibt RGB888 R7 R6 R5 R4 R3 R2 R1 R0 G7 G6 G5 G4 G3 G2 G1 G0 B7 B6 B5 B4 B3 B2 B1 B0

  16bit RGB656 R7 R6 R5 R4 R3 G7 G6 G5 G4 G3 G2 B7 B6 B5 B4 B3

  量化位數從8bit到5bit或6bit,取原8bit的高位,量化上做了壓縮,卻損失了精度。

  量化補償,舉例:

  16bit RGB565 -> 24bit RGB888 的轉換

  16bit RGB656 R4 R3 R2 R1 R0 G5 G4 G3 G2 G1 G0 B4 B3 B2 B1 B0

  24ibt RGB888 R4 R3 R2 R1 R0 0 0 0 G5 G4 G3 G2 G1 G0 0 0 B4 B3 B2 B1 B0 0 0 0

  24ibt RGB888 R4 R3 R2 R1 R0 R2 R1 R0 G5 G4 G3 G2 G1 G0 G1 G0 B4 B3 B2 B1 B0 B2 B1 B0

  說明:第二行的 24bit RGB888 數據爲轉換後,未進行補償的數據,在精度上會有損失

  第三行的 24bit RGB888 數據爲經過量化補償的數據,對低位做了量化補償

  可以很容易的證明,這樣的補償方法是一種合理的線性補償。補償的原理很簡單,大家仔細想一下就明白了,因此不再詳細說明。

  總結一下:

  量化壓縮的方法:三個字取高位

  量化補償的方法:

  1. 將原數據填充至高位

  2. 對於低位,用原始數據的低位進行補償

  3. 如果仍然有未填充的位,繼續使用原始數據的低位進行循環補償

  解釋一下循環補償的概念:

  8bit RGB332 -> 24bit RGB888 的轉換

  8bit RGB332 R2 R1 R0 G2 G1 G0 B1 B0

  24bit RGB888 R2 R1 R0 0 0 0 0 0 G2 G1 G0 0 0 0 0 0 B1 B0 0 0 0 0 0 0

  24bit RGB888 R2 R1 R0 R2 R1 R0 0 0 G2 G1 G0 G2 G1 G0 0 0 B1 B0 B1 B0 0 0 0 0

  24bit RGB888 R2 R1 R0 R2 R1 R0 R2 R1 G2 G1 G0 G2 G1 G0 G2 G1 B1 B0 B1 B0 B1 B0 0 0

  24bit RGB888 R2 R1 R0 R2 R1 R0 R2 R1 G2 G1 G0 G2 G1 G0 G2 G1 B1 B0 B1 B0 B1 B0 B1 B0

  看了這個,應該明白則麼回事了吧,其中B分量,進行了四輪的補償,達到要求。

  量化補償的必要性,從直覺上講,我所提出的這種補償方法是正確的(因爲我並沒有嚴格的去證明),進行這樣的補償,在做色彩各式轉換的時候,能夠明顯的改善色彩效果,減少精度上的損失。

 bitmap圖片是一個RGB888,每個像素由3個字節組成,R->8bit,G->8bit,B->8bit;

  RGB565 的每個pixels是由2字節組成,R->5bit,G->6bit,B->5bit。

轉換的思路是取出原圖的點,對沒個採樣進行運算。

#define RGB565_MASK_RED        0xF800   
  1. #define RGB565_MASK_GREEN                         0x07E0   
  2. #define RGB565_MASK_BLUE                         0x001F   
  3.   
  4. void rgb565_2_rgb24(BYTE *rgb24, WORD rgb565)  
  5. {   
  6.  //extract RGB   
  7.  rgb24[2] = (rgb565 & RGB565_MASK_RED) >> 11;     
  8.  rgb24[1] = (rgb565 & RGB565_MASK_GREEN) >> 5;  
  9.  rgb24[0] = (rgb565 & RGB565_MASK_BLUE);  
  10.   
  11.  //amplify the image   
  12.  rgb24[2] <<= 3;  
  13.  rgb24[1] <<= 2;  
  14.  rgb24[0] <<= 3;  
  15. }   
  1. #define RGB565_MASK_RED        0xF800   
  2. #define RGB565_MASK_GREEN                         0x07E0   
  3. #define RGB565_MASK_BLUE                         0x001F   
  4.   
  5. void rgb565_2_rgb24(BYTE *rgb24, WORD rgb565)  
  6. {   
  7.  //extract RGB   
  8.  rgb24[2] = (rgb565 & RGB565_MASK_RED) >> 11;     
  9.  rgb24[1] = (rgb565 & RGB565_MASK_GREEN) >> 5;  
  10.  rgb24[0] = (rgb565 & RGB565_MASK_BLUE);  
  11.   
  12.  //amplify the image   
  13.  rgb24[2] <<= 3;  
  14.  rgb24[1] <<= 2;  
  15.  rgb24[0] <<= 3;  
  16. }   

  1. USHORT rgb_24_2_565(int r, int g, int b)  
  2. {  
  3.     return (USHORT)(((unsigned(r) << 8) & 0xF800) |   
  4.             ((unsigned(g) << 3) & 0x7E0)  |  
  5.             ((unsigned(b) >> 3)));  
  6. }  
  1. USHORT rgb_24_2_565(int r, int g, int b)  
  2. {  
  3.     return (USHORT)(((unsigned(r) << 8) & 0xF800) |   
  4.             ((unsigned(g) << 3) & 0x7E0)  |  
  5.             ((unsigned(b) >> 3)));  
  6. }  

USHORT rgb_24_2_555(int r, int g, int b)  
  1. {  
  2.     return (USHORT)(((unsigned(r) << 7) & 0x7C00) |   
  3.             ((unsigned(g) << 2) & 0x3E0)  |  
  4.             ((unsigned(b) >> 3)));  
  5. }  
  6.   
  7. COLORREF rgb_555_2_24(int rgb555)  
  8. {  
  9.     unsigned r = ((rgb555 >> 7) & 0xF8);  
  10.     unsigned g = ((rgb555 >> 2) & 0xF8);  
  11.     unsigned b = ((rgb555 << 3) & 0xF8);  
  12.     return RGB(r,g,b);  
  13. }  
  14.   
  15. void rgb_555_2_bgr24(BYTE* p, int rgb555)  
  16. {  
  17.     p[0] = ((rgb555 << 3) & 0xF8);  
  18.     p[1] = ((rgb555 >> 2) & 0xF8);  
  19.     p[2] = ((rgb555 >> 7) & 0xF8);  
  20. }  
 
  1. USHORT rgb_24_2_555(int r, int g, int b)  
  2. {  
  3.     return (USHORT)(((unsigned(r) << 7) & 0x7C00) |   
  4.             ((unsigned(g) << 2) & 0x3E0)  |  
  5.             ((unsigned(b) >> 3)));  
  6. }  
  7.   
  8. COLORREF rgb_555_2_24(int rgb555)  
  9. {  
  10.     unsigned r = ((rgb555 >> 7) & 0xF8);  
  11.     unsigned g = ((rgb555 >> 2) & 0xF8);  
  12.     unsigned b = ((rgb555 << 3) & 0xF8);  
  13.     return RGB(r,g,b);  
  14. }  
  15.   
  16. void rgb_555_2_bgr24(BYTE* p, int rgb555)  
  17. {  
  18.     p[0] = ((rgb555 << 3) & 0xF8);  
  19.     p[1] = ((rgb555 >> 2) & 0xF8);  
  20.     p[2] = ((rgb555 >> 7) & 0xF8);  
  21. }  

 

#define RGB565_Val(r,g,b) (WORD)((r)<<11 | (g)<<5 | (b))   
  1. WORD rgb555_2_rgb565(WORD rgb555)  
  2. {  
  3.    BYTE r,g,b;  
  4.    FLOAT fRate = 63/31;  
  5.    //Get R G B    
  6.    r = (BYTE)(((rgb555 >> 7) & 0xF8)>>3);  
  7.    g = (BYTE)((((rgb555 >> 2) & 0xF8)>>3)*fRate);  
  8.    b = (BYTE)(((rgb555 << 3) & 0xF8)>>3);  
  9.    *(WORD *)pDest = RGB565_Val(RDest,GDest,BDest);  
發佈了28 篇原創文章 · 獲贊 2 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章