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;
}
时间: 2024-10-26 17:18:30

RGB565的转换的相关文章

RGB888与RGB565互相转换原理

一.概念 BPP(Bits Per Pixels):(像素深度)一般指像素深度. 二.背景 计算机中图像是以RGB888格式显示图像的,24位图(BPP)每个像素保存了32bit的数据,即RGB888+Alpha,Alpha就是半透明填充字节……但是对于真彩的图像而言,肉眼在16bit的时候已经难以分辨了,因此,有些时候,可以讲RGB888转换为RGB565来存储,减少了存储器的容量的同时,降低了数据量:在后端显示的时候,再次把RGB565转换为RGB888,实现数据宽度的匹配! 原文地址:ht

RGB565 转换 BMP24

今晚有心情,就做完了BMP16(RGB565) 转换成BMP24 的小程序.其中最关键的地方是: // k,WORD类型,是RGB565 的一个点的数据(可以认为是灰度). r=(k & 0x1F)  <<(0 +3);            g=(k & 0x07E0)>>(5 -2);            b=(k & 0xF800)>>(11-3); RGB565 的顺序是: BGRBMP24的顺序是:RGB在写入文件的时候注意转过来.由

量化补偿与量化压缩

学习博客:http://lhtao31.blog.163.com/blog/static/2972647020103814044158/ 最近在学习调试摄像头,配置OV7670摄像头采集到的数据是RGB565,移植别人的代码,从ZYNQ移植到Basys3,VGA输出引脚需要又RGB565转到RGB444,我采用分别取RGB565三分量高位的方法,最终显示输出,视频图像会变得更模糊,这是由于在转换的时候去掉低位会损失精度.而OV7670的图像采集效果也是不怎么样,所以后面会尝试配置OV7725,追

基于FPGA的彩色图像转灰度算法实现

昨天才更新了两篇博客,今天又要更新了,并不是我垃圾产,只不过这些在上个月就已经写好了,只是因为比赛忙,一直腾不出时间整理出来发表而已,但是做完一件事情总感觉不写一博文总结一下就少点什么,所以之后的一段时间里我会把我这学期学到的一些东西陆续整理出来发表,给自己一个总结交代. 将彩色图像转化为灰度的方法有两种,一个是令RGB三个分量的数值相等,输出后便可以得到灰度图像,另一种是转化为YCbCr格式,将Y分量提取出来,YCbCr格式中的Y分量表示的是图像的亮度和浓度所以只输出Y分量,得到的图像就是灰度

基于FPGA的RGB565_YCbCr_Gray算法实现

前面我们讲了基于FPGA用VGA显示一副静态图片,那么接下来我们就接着前面的工程来实现我们图像处理的基础算法里最简单的一个那就是彩色图像转灰度的实现. 将彩色图像转化为灰度的方法有两种,一个是令RGB三个分量的数值相等,输出后便可以得到灰度图像,另一种是转化为YCbCr格式,将Y分量提取出来,YCbCr格式中的Y分量表示的是图像的亮度和浓度所以只输出Y分量,得到的图像就是灰度图像了.我在这里选择第二种方法实现. YCBCr是通过有序的三元组来表示的,三元由Y(Luminance).Cb(Chro

关于yuv 的pack(紧缩格式)和planner(平面格式)格式 [转]

关于yuv 格式 YUV 格式通常有两大类:打包(packed)格式和平面(planar)格式.前者将 YUV 分量存放在同一个数组中,通常是几个相邻的像素组成一个宏像素(macro-pixel);而后者使用三个数组分开存放 YUV 三个分量,就像是一个三维平面一样. 几种常见的yuv格式 1.YUV422 Planar 这里,Y\U\V数据是分开存放的,每两个水平Y采样点,有一个Cb和一个Cr采样点,如下图 ffmpeg 中的定义  PIX_FMT_YUV422P,   ///< planar

16位bmp文件中RGB555转RGB565算法

做tft彩屏显示图片的时候,显示16位位图,显示屏的显示模式为RGB565.使用img2lcd转换后的16位bmp,显示出来后,颜色有偏差:转换为565格式的bin文件,显示完全正常,可以确定转换为bmp后,格式为RGB555.网上查找相关资料显示,Windows 图片查看器显示正常的图片,均为RGB555格式,系统自带画图画图工具保存时,不支持将文件保存为16位位图格式. 以下为555转565的程序片段,转换后的结果和使用img2lcd软件保存为565格式的结果完全相同.转换的结果其实就是将原

BMP RGB888转RGB565 +上下翻转+缩放

典型的BMP图像文件由四部分组成: (1) 位图头文件数据结构,它包含BMP图像文件的类型.文件大小和位图起始位置等信息: typedef struct tagBITMAPFILEHEADER { WORD bfType;//位图文件的类型,必须为BM(1-2字节) DWORD bfSize;//位图文件的大小,以字节为单位(3-6字节,低位在前) WORD bfReserved1;//位图文件保留字,必须为0(7-8字节) WORD bfReserved2;//位图文件保留字,必须为0(9-1

C语言颜色转换宏

C语言颜色转换宏 #define COLOR_BPP16_RGB555 /* Win RGB */ #define COLOR_RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16))) #define COLOR_RGBA(r,g,b,a) ((COLORREF)((((DWORD)(BYTE)(a))<<24)|COLOR_RGB(r,g,b))) /* W