RGB格式轉換的實現

一、實驗目的

  1. RGB格式儲存特點。
  2. RGB格式轉換的實現過程。

二、實驗內容

  1. RGB888 RGB565 兩種格式存儲特點
  2. RGB565獲取每一個分量的數據值的實現寫出來。
  3. RGB888轉565的實現函數
  4. 565轉888的實現函數(中間的顏色值是有精度損失、最終的顏色值經過量化補償的操作)
  5. 實現一個完整的測試程序
    linux平臺下面通過打開bmp圖片的方式,利用之前實現的函數對其格式進行轉換,把最終轉換的圖片顏色數據輸出出來

三.實驗結果分析

  1. RGB888/RGB565 兩種格式存儲特點
    RGB色彩模式是工業界的一種顏色標準,是通過對紅(R)、綠(G)、藍(B)三個顏色通道的變化以及它們相互之間的疊加來得到各式各樣的顏色的,RGB即是代表紅、綠、藍三個通道的顏色,這個標準幾乎包括了人類視力所能感知的所有顏色,是目前運用最廣的顏色系統之一。 在電腦中,RGB的所謂“多少”就是指亮度,並使用整數來表示。通常情況下RGB各有256級亮度,用數字表示爲從0、1、2…直到255。在0時燈最弱是關掉的,而在255時燈最高。當三色數值相同時爲無色彩的灰色度,而三色都爲255時爲最亮的白色,都爲0時爲黑色;
    RGB565使用16位表示一個像素,這16位中的5位用於R,6位用於G,5位用於B。共有兩個字節。
    RGB888使用24位表示一個像素,這24位中的8位用於R,8位用於G,8位用於B。共有三個字節。

  2. RGB565獲取每一個分量的數據值的實現寫出來。
    可以組合使用屏蔽字和移位操作來得到RGB各分量的值:
    具體實現過程如圖3-1所示

#define RGB555_MASK_RED 0x7C00
#define RGB555_MASK_GREEN 0x03E0
#define RGB555_MASK_BLUE 0x001F
R = (wPixel & RGB555_MASK_RED) >> 10; 
G = (wPixel & RGB555_MASK_GREEN) >> 5; 
B = wPixel & RGB555_MASK_BLUE;

RGB565獲取每一個分量

3: RGB888轉565的實現函數
RGB888->RGB565而言:其轉換的具體思路如下:

1.取RGB888中第一個字節的高5位作爲轉換後的RGB565的第一個字節的低5位
2.取RGB888中第二個字節的高3位作爲轉換後的RGB565第二個字節的低3位
3.取RGB888中第二個字節的第4–6位,作爲轉換後的RGB565第一個字節的高3位
4.取RGB888中第三個字節的高5位作爲轉換後的RGB565第二個字節的高5位

unsigned short rgb_24_to_565(unsigned short r, unsigned short g, unsigned short b)  
{  
    return ((r << 8) & 0xF800) | ((g << 3) & 0x07E0) | ((b >> 3) & 0x001f);
}

代碼中的具體實現如下圖3-2所示

*RGB888轉565的實現

4: 565轉888的實現函數(中間的顏色值有精度損失、最終的顏色值經過量化補償的操作)
RGB565->RGB888

1.取RGB565第一個字節中低5位作爲RGB888第一個字節的高5位
2.取RGB565第二個字節中的低3位,將其左移5位,作爲RGB888第二個字節的高3位
3.取RGB565第一個字節的高3位將其右移5位,作爲RGB888第二個字節的4–6位
4.取RGB565第二個字節中的高5位作爲RGB888第三個字節

void rgb565_to_rgb24(BYTE *rgb24, unsigned short rgb565)  
{   
 //extract RGB  
rgb24[2] = (rgb565 & RGB565_MASK_RED) >> 11;     
    rgb24[1] = (rgb565 & RGB565_MASK_GREEN) >> 5;  
    rgb24[0] = (rgb565 &  RGB565_MASK_BLUE);  
//amplify the image  
    rgb24[2] <<= 3;  
    rgb24[1] <<= 2;  
    rgb24[0] <<= 3; 
    rgb24[2] = rgb24[2] | ((rgb24[2] & 0x38) >> 3);
    rgb24[1] = rgb24[1] | ((rgb24[1] & 0x0c) >> 2)
    rgb24[0] = rgb24[0] | ((rgb24[0] & 0x38) >> 3);
}  

具體過程實現如圖3-3所示
565轉888

5:量化補償
量化補償的方法:

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

16bit RGB565 -> 24bit RGB888 的轉換
16bit RGB656: R4 R3 R2 R1 R0 G5 G4 G3 G2 G1 G0 B4 B3 B2 B1 B0

1: 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
2: 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 數據爲經過量化補償的數據,對低位做了量化補償

四:實現完整的測試程序

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#pragma pack(2)
/*定義WORD爲兩個字節的類型*/
typedef unsigned short  WORD;
/*定義DWORD爲e四個字節的類型*/
typedef unsigned long  DWORD;
/*位圖文件頭*/
typedef struct tagBITMAPFILEHEADER{
           WORD bType; /* 文件標識符 位圖類別*/
           DWORD bSize; /* BMP圖像文件的大小 */
           WORD bReserved1; /* 保留值,總爲0 */
           WORD bReserved2; /* 保留值,總爲0 */
           DWORD  bfOffBits;/* BMP圖像數據的地址*/
} BMPFILEHEADER;
 /*位圖信息頭*/
typedef struct tagBITMAPINFOHEADER{
           DWORD bInfoSize; /* 信息頭的大小 */
           DWORD bWidth; /* 圖像的寬度 */
           DWORD bHeight; /* 圖像的高度 */
           WORD bPlanes; /* 圖像的位面數 */
           WORD bBitCount; /* 每個像素的位數 */
           DWORD bCompression; /* 壓縮類型 */
           DWORD bmpImageSize; /* 圖像的大小,以字節爲單位 */
           DWORD bXPelsPerMeter; /* 水平分辨率 */
           DWORD bYPelsPerMeter; /* 垂直分辨率 */
           DWORD bClrUsed; /* 使用的色彩數 */
           DWORD bClrImportant; /* 重要的顏色數 */
} BMPINF; 

/*調色板*/
typedef struct tagRGBQUAD
{
          WORD rgbBlue; /* 藍色強度 */
          WORD rgbGreen; /* 綠色強度 */
          WORD rgbRed; /* 紅色強度 */
          WORD rgbReversed; /* 保留值 */
} RGBQUAD;
void rgb565_to_rgb888(unsigned char *image,unsigned char *image888) 
{ 
          unsigned char R,G,B; 
          B=(*image) & 0x1F;//000BBBBB 
          G=( *(image+1) << 3 ) & 0x38 + ( *image >> 5 ) & 0x07 ;//得到00GGGGGG00 
          R=( *(image+1) >> 3 ) & 0x1F; //得到000RRRRR 
         *(image888+0)=B * 255 / 63; // 把5bits映射到8bits去,有多種算法。 
         *(image888+1)=G * 255 / 127; 
         *(image888+2)=R * 255 / 63; 
         printf("1%x 1%x 1%x \n",*image888,*(image888+1),*(image888+2));
}
unsigned short rgb_24_to_565(unsigned short r, unsigned short g, unsigned short b)  
{  
          short sh=((r << 8) & 0xF800) | ((g << 3) & 0x07E0) | ((b >> 3) & 0x001f);
          unsigned char *ch=(char *)&sh;
          unsigned char ch1=ch[0];
          unsigned char ch2=ch[1];
          printf("%x %x\n",ch1,ch2);
          return  sh;
}
void change(char filepath1[]){
            FILE *fp;
            BMPFILEHEADER fileHeader;
            BMPINF infoHeader;
            long offset, bmpImageSize, width, height, bytesPerPixel, size, bitCount;
            WORD c;
            unsigned char red32, green32, blue32, x32, red565, green565, blue565;
            unsigned short rgb565;

//打開文件
if((fp = fopen(filepath1, "rb")) == NULL){
             printf("Cann't open the file!\n");
            exit(0);}
fseek(fp, 0, 0);//文件指針偏移位置
fread(&fileHeader, sizeof(fileHeader), 1, fp);
fread(&infoHeader, sizeof(infoHeader), 1, fp);
if(infoHeader.bBitCount==16){
printf("原文件是RGB565格式的\n");
unsigned char ch1[2],ch2[3];
do{
fread(ch1,2,1,fp);
rgb565_to_rgb888(ch1,ch2);
            printf("565blue32=0x%x,green32=0x%x,red32=0x%x.\n",blue32\,green32,red32);         
            printf("%x %x %x\n",ch2[0],ch2[1],ch2[2]);
}while(!feof(fp));
}else{
printf("原文件是RGB888格式的\n");
unsigned char ch2[3];
do{
            fread(ch2,3,1,fp);
            fread(&blue32,sizeof(unsigned char),1,fp);
            fread(&green32,sizeof(unsigned char),1,fp);
            fread(&red32,sizeof(unsigned char),1,fp);    
            short sh=rgb_24_to_565(ch2[2],ch2[1],ch2[0]);
            printf("888blue32=0x%x,green32=0x%x,red32=0x%x.\n",blue32,green32,red32);
}while(!feof(fp));
}fclose(fp);
}

int main(){
                 change("background_1.bmp");
                 return 0;
}

嵌入式導論之RGB格式轉換.doc

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章