RGB565的轉換


     RGB色彩模式也就是“紅綠藍”模式是一種顏色標准,是通過對紅(R)、綠(G)、藍(B)三種顏色通道的變化以及它們相互之間的疊加來得到各式各樣的顏色的,RGB即是代表紅、綠、藍三個通道的顏色,這個標准幾乎囊括了人類視力所能感知的所有顏色,是目前運用最廣的顏色系統之一。

1、RGB565格式說明

      RGB565彩色模式, 一個像素占兩個字節, 其中:第一個字節的前5位用來表示R(Red),第一個字節的后三位+第二個字節的前三位用來表示G(Green),第二個字節的后5位用來表示B(Blue)。如:15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0   

     而bitmap圖片是一個RGB888,每個像素由3個字節24位組成,R->8bit,G->8bit,B->8bit;RGB565  的每個pixels是由2字節組成,R->5bit,G->6bit,B->5bit。轉換的思路是取出原圖的點,對每個采樣進行運算。

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}

可以修正,比如(當然人眼無法感覺,但是RG888-RGB565-RGB888的時候更好補償)

R:197=>197>>3=24

R:197=192+5=>24+0.625≈25

所以

R5=R[2] ? R[7:3]+1 : R[7:3];

G5=G[1] ? G[7:2]+1 : G[7:2];

B5=B[2] ? B[7:3]+1 : B[7:3];

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}

 

 

總結一下:

1、量化壓縮的方法:

   三個字節對應取高位

 

2、量化補償的方法:

 (1) 將原數據填充至高位

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

 

3、RGB565互轉代碼

 

#define RGB565_MASK_RED        0xF800   
#define RGB565_MASK_GREEN    0x07E0   
#define RGB565_MASK_BLUE       0x001F   

void rgb565_2_rgb24(BYTE *rgb24, WORD rgb565)    //分離出單獨的RGB
{    
 
      rgb24[2] = (rgb565 & RGB565_MASK_RED) >> 11;      

      rgb24[1] = (rgb565 & RGB565_MASK_GREEN) >> 5;   
      
      rgb24[0] = (rgb565 & RGB565_MASK_BLUE);   

      //往高位移動填滿單字節的8位
      rgb24[2] <<= 3;   
      rgb24[1] <<= 2;   
      rgb24[0] <<= 3;   
}

 

 

  

 

 

下面的代碼來自這個網址:

http://bbs.csdn.net/topics/350153377

 

#ifndef WIDTHBYTES
#define WIDTHBYTES(bits) ((DWORD)(((bits)+31) & (~31)) / 8)
#endif
// BITMAPINFOHEADER m_bmih;
// BYTE *m_pR;
// BYTE *m_pG;
// BYTE *m_pB;
BOOL CImageProcessor::LoadFileFromBitmap(LPCTSTR lpFileName)
{
    if(lpFileName == NULL)
    {
        return FALSE;
    }
 
    HANDLE hFile = ::CreateFile(lpFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
    if(hFile == INVALID_HANDLE_VALUE)
    {
        return FALSE;
    }
 
    BOOL bRet = FALSE;
 
    do
    {
        LARGE_INTEGER liSize;
        liSize.QuadPart = 0;
        ::GetFileSizeEx(hFile, &liSize);
 
        BITMAPFILEHEADER bmfh;
        BITMAPINFOHEADER bmih;
 
        DWORD dwByteRead = 0;
        ::ReadFile(hFile, &bmfh, sizeof(bmfh), &dwByteRead, NULL);
        if(dwByteRead < sizeof(bmfh))
        {
            break;
        }
 
        if(bmfh.bfType != 'MB' || bmfh.bfSize > liSize.QuadPart || bmfh.bfOffBits > liSize.QuadPart)
        {
            break;
        }
 
        dwByteRead = 0;
        ::ReadFile(hFile, &bmih, sizeof(bmih), &dwByteRead, NULL);
        if(dwByteRead < sizeof(bmih))
        {
            break;
        }
 
        int nBitmapSize = abs(bmih.biHeight) * WIDTHBYTES(bmih.biWidth * bmih.biBitCount);
        if(bmih.biPlanes != 1)
        {
            break;
        }
        if(bmih.biBitCount != 1 && bmih.biBitCount != 4 && bmih.biBitCount != 8 && bmih.biBitCount != 16 && bmih.biBitCount != 24 && bmih.biBitCount != 32)
        {
            break;
        }
        if(bmih.biCompression != BI_RGB && bmih.biCompression != BI_BITFIELDS)
        {
            break;
        }
        if(bmih.biWidth <= 0 || bmih.biHeight == 0)
        {
            break;
        }
        if(bmfh.bfOffBits + nBitmapSize > liSize.QuadPart)
        {
            break;
        }
 
        m_pR = new BYTE[bmih.biWidth * abs(bmih.biHeight)];
        m_pG = new BYTE[bmih.biWidth * abs(bmih.biHeight)];
        m_pB = new BYTE[bmih.biWidth * abs(bmih.biHeight)];
 
        if(bmih.biBitCount < 16)
        {
            //...
        }
        else if(bmih.biBitCount == 16)
        {
            //...
        }
        else if(bmih.biBitCount == 24)
        {
            ::SetFilePointer(hFile, bmfh.bfOffBits, NULL, SEEK_SET);
 
            BYTE *pData = new BYTE[nBitmapSize];
 
            dwByteRead = 0;
            ::ReadFile(hFile, pData, nBitmapSize, &dwByteRead, NULL);
 
            BYTE *pR = m_pR;
            BYTE *pG = m_pG;
            BYTE *pB = m_pB;
 
            for(int j = 0; j < abs(bmih.biHeight); j++)
            {
                BYTE *pTemp = pData + WIDTHBYTES(bmih.biWidth * bmih.biBitCount) * j;
                for(int i = 0; i < bmih.biWidth; i++)
                {
                    *pB++ = *pTemp++;
                    *pG++ = *pTemp++;
                    *pR++ = *pTemp++;
                }
            }
 
            delete[] pData;
        }
        else if(bmih.biBitCount == 32)
        {
            //...
        }
 
        memcpy(&m_bmih, &bmih, sizeof(m_bmih));
 
        bRet = TRUE;
    }
    while(0);
 
    CloseHandle(hFile);
 
    return bRet;
}
 
BOOL CImageProcessor::SaveFile565(HANDLE hFile)
{
    BITMAPFILEHEADER bmfh;
    BITMAPINFOHEADER bmih;
    memset(&bmfh, 0, sizeof(bmfh));
    memset(&bmih, 0, sizeof(bmih));
 
    int nBitmapSize = abs(m_bmih.biHeight) * WIDTHBYTES(m_bmih.biWidth * 16);
 
    bmfh.bfType = 'MB';
    bmfh.bfOffBits = sizeof(bmfh) + sizeof(bmih) + 12;
    bmfh.bfSize = bmfh.bfOffBits + nBitmapSize;
 
    bmih.biSize = sizeof(bmih);
    bmih.biWidth = m_bmih.biWidth;
    bmih.biHeight = m_bmih.biHeight;
    bmih.biPlanes = 1;
    bmih.biBitCount = 16;
    bmih.biCompression = BI_BITFIELDS;
    bmih.biSizeImage = nBitmapSize;
 
    BYTE *pData = new BYTE[nBitmapSize];
    memset(pData, 0, nBitmapSize);
 
    BYTE *pR = m_pR;
    BYTE *pG = m_pG;
    BYTE *pB = m_pB;
 
    for(int j = 0; j < abs(bmih.biHeight); j++)
    {
        WORD *pTemp = (WORD *)(pData + WIDTHBYTES(bmih.biWidth * 16) * j);
 
        for(int i = 0; i < bmih.biWidth; i++)
        {
#if 1
            *pTemp++ = ((WORD)(*pR++ << 8) & 0xf800) | ((WORD)(*pG++ << 3) & 0x07e0) | ((WORD)(*pB++ >> 3) & 0x001f);
#else
            int nR = (*pR++ + 4) >> 3;
            int nG = (*pG++ + 2) >> 2;
            int nB = (*pB++ + 4) >> 3;
            if(nR > 31) nR = 31;
            if(nG > 63) nG = 63;
            if(nB > 31) nB = 31;
            *pTemp++ = (nR << 11) | (nG << 5) | nB;
#endif
        }
    }
 
    DWORD nRGBMask[3];
    nRGBMask[0] = 0xf800;
    nRGBMask[1] = 0x07e0;
    nRGBMask[2] = 0x001f;
 
    DWORD dwByteWritten = 0;
    ::WriteFile(hFile, &bmfh, sizeof(bmfh), &dwByteWritten, NULL);
    ::WriteFile(hFile, &bmih, sizeof(bmih), &dwByteWritten, NULL);
    ::WriteFile(hFile, nRGBMask, sizeof(nRGBMask), &dwByteWritten, NULL);
    ::WriteFile(hFile, pData, nBitmapSize, &dwByteWritten, NULL);
 
    delete[] pData;
 
    return TRUE;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM