zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    my34_脚本冥等添加自动任务-mysql监控部署
    zabbix4.2 安装
    面试题12:字符串无重复子串的最大长度
    面试题11:二叉树的非递归前、中、后、层级遍历
    面试题10:二叉树的最大路径和
    面试题9:数组堆化、堆的插入、堆的删除、堆排序
    面试题8:无序数组的最大差值
    面试题7:判断链表是否有环,返回环的入口点
    面试题6:二叉树最近公共节点(LCA)《leetcode236》
    面试题6:二叉树转单链表
  • 原文地址:https://www.cnblogs.com/zhangjiansheng/p/6683163.html
Copyright © 2011-2022 走看看