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, , NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
return FALSE;
} BOOL bRet = FALSE; do
{
LARGE_INTEGER liSize;
liSize.QuadPart = ;
::GetFileSizeEx(hFile, &liSize); BITMAPFILEHEADER bmfh;
BITMAPINFOHEADER bmih; DWORD dwByteRead = ;
::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 = ;
::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 != )
{
break;
}
if(bmih.biBitCount != && bmih.biBitCount != && bmih.biBitCount != && bmih.biBitCount != && bmih.biBitCount != && bmih.biBitCount != )
{
break;
}
if(bmih.biCompression != BI_RGB && bmih.biCompression != BI_BITFIELDS)
{
break;
}
if(bmih.biWidth <= || bmih.biHeight == )
{
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 < )
{
//...
}
else if(bmih.biBitCount == )
{
//...
}
else if(bmih.biBitCount == )
{
::SetFilePointer(hFile, bmfh.bfOffBits, NULL, SEEK_SET); BYTE *pData = new BYTE[nBitmapSize]; dwByteRead = ;
::ReadFile(hFile, pData, nBitmapSize, &dwByteRead, NULL); BYTE *pR = m_pR;
BYTE *pG = m_pG;
BYTE *pB = m_pB; for(int j = ; j < abs(bmih.biHeight); j++)
{
BYTE *pTemp = pData + WIDTHBYTES(bmih.biWidth * bmih.biBitCount) * j;
for(int i = ; i < bmih.biWidth; i++)
{
*pB++ = *pTemp++;
*pG++ = *pTemp++;
*pR++ = *pTemp++;
}
} delete[] pData;
}
else if(bmih.biBitCount == )
{
//...
} memcpy(&m_bmih, &bmih, sizeof(m_bmih)); bRet = TRUE;
}
while(); CloseHandle(hFile); return bRet;
} BOOL CImageProcessor::SaveFile565(HANDLE hFile)
{
BITMAPFILEHEADER bmfh;
BITMAPINFOHEADER bmih;
memset(&bmfh, , sizeof(bmfh));
memset(&bmih, , sizeof(bmih)); int nBitmapSize = abs(m_bmih.biHeight) * WIDTHBYTES(m_bmih.biWidth * ); bmfh.bfType = 'MB';
bmfh.bfOffBits = sizeof(bmfh) + sizeof(bmih) + ;
bmfh.bfSize = bmfh.bfOffBits + nBitmapSize; bmih.biSize = sizeof(bmih);
bmih.biWidth = m_bmih.biWidth;
bmih.biHeight = m_bmih.biHeight;
bmih.biPlanes = ;
bmih.biBitCount = ;
bmih.biCompression = BI_BITFIELDS;
bmih.biSizeImage = nBitmapSize; BYTE *pData = new BYTE[nBitmapSize];
memset(pData, , nBitmapSize); BYTE *pR = m_pR;
BYTE *pG = m_pG;
BYTE *pB = m_pB; for(int j = ; j < abs(bmih.biHeight); j++)
{
WORD *pTemp = (WORD *)(pData + WIDTHBYTES(bmih.biWidth * ) * j); for(int i = ; i < bmih.biWidth; i++)
{
#if 1
*pTemp++ = ((WORD)(*pR++ << ) & 0xf800) | ((WORD)(*pG++ << ) & 0x07e0) | ((WORD)(*pB++ >> ) & 0x001f);
#else
int nR = (*pR++ + ) >> ;
int nG = (*pG++ + ) >> ;
int nB = (*pB++ + ) >> ;
if(nR > ) nR = ;
if(nG > ) nG = ;
if(nB > ) nB = ;
*pTemp++ = (nR << ) | (nG << ) | nB;
#endif
}
} DWORD nRGBMask[];
nRGBMask[] = 0xf800;
nRGBMask[] = 0x07e0;
nRGBMask[] = 0x001f; DWORD dwByteWritten = ;
::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;
}

RGB565的转换的更多相关文章

  1. RGB565 转换 BMP24

    今晚有心情,就做完了BMP16(RGB565) 转换成BMP24 的小程序.其中最关键的地方是: // k,WORD类型,是RGB565 的一个点的数据(可以认为是灰度). r=(k & 0x ...

  2. RGB888->RGB565->RGB888

     转自CB的博客:http://blog.chinaaet.com/detail/28298 在我们的计算机中,图像是以RGB888显示的,24位图每个像素保存了32bit的数据,即RGB888+Al ...

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

    关于yuv 格式 YUV 格式通常有两大类:打包(packed)格式和平面(planar)格式.前者将 YUV 分量存放在同一个数组中,通常是几个相邻的像素组成一个宏像素(macro-pixel);而 ...

  4. YUV422 YUV420 Planar \ Semi-Planar \ Interleaved

    关于yuv 格式 YUV 格式通常有两大类:打包(packed)格式和平面(planar)格式.前者将 YUV 分量存放在同一个数组中,通常是几个相邻的像素组成一个宏像素(macro-pixel);而 ...

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

    昨天才更新了两篇博客,今天又要更新了,并不是我垃圾产,只不过这些在上个月就已经写好了,只是因为比赛忙,一直腾不出时间整理出来发表而已,但是做完一件事情总感觉不写一博文总结一下就少点什么,所以之后的一段 ...

  6. 基于FPGA的RGB565_YCbCr_Gray算法实现

    前面我们讲了基于FPGA用VGA显示一副静态图片,那么接下来我们就接着前面的工程来实现我们图像处理的基础算法里最简单的一个那就是彩色图像转灰度的实现. 将彩色图像转化为灰度的方法有两种,一个是令RGB ...

  7. ILI9341液晶显示

    17.1液晶显示原理 TFT-LCD(Thin Film Transistor Liquid Crystal Display)即薄膜晶体管液晶显示器,是微电子技术与液晶显示器技术巧妙结合的的一种技术. ...

  8. YUV到RGB的转换

    以下内容来源于网络,下面三个链接里的内容是比较好的,感谢博主的分享. http://blog.csdn.net/housisong/article/details/1859084 http://blo ...

  9. YUV / RGB 格式及快速转换算法

    1 前言 自然界的颜色千变万化,为了给颜色一个量化的衡量标准,就需要建立色彩空间模型来描述各种各样的颜色,由于人对色彩的感知是一个复杂的生理和心理联合作用 的过程,所以在不同的应用领域中为了更好更准确 ...

随机推荐

  1. 《Javascript高级程序设计》阅读记录(七):第七章

    <Javascript高级程序设计>中,2-7章中已经涵盖了大部分精华内容,所以摘录到博客中,方便随时回忆.本系列基本完成,之后的章节,可能看情况进行摘录. 这个系列以往文字地址: < ...

  2. [SP16549]QTREE6

    luogu vjudge 题意 给你一棵n个点的树,编号1~n.每个点可以是黑色,可以是白色.初始时所有点都是黑色.支持两种操作: 0 u:询问有多少个节点v满足路径u到v上所有节点(包括)都拥有相同 ...

  3. 1、Monkey入门准备教程

    1.前提需要Android环境 ADT:链接: https://pan.baidu.com/s/1QN6EJh46cJGvUBaMZjtiWw 密码: a7zu Eclipse:https://www ...

  4. 极路由U-boot解锁刷root固件教程,root后可刷华硕、如意云等多种固件,附赠全套刷软

    9008正式版固件将会封堵此漏洞,想root的同学尽快了.安装新工具箱里的root保留,可升级官方最新固件并保留root. 此方法并非本人原创,只是将root的过程和经验做个总结,比较适合菜鸟做参考, ...

  5. StringBuilder、StringBuffer、String区别

          相信大家对 String 和 StringBuffer 的区别也已经很了解了,但是估计还是会有很多同志对这两个类的工作原理有些不清楚的地方,今天重新把这个概念给大家复习一下,顺便牵出 J2 ...

  6. 寻找php.ini之旅

    /usr/local/php-fpm/lib/php.ini 可以通过phpinfo()来查看 https://www.cnblogs.com/ChineseMoonGod/p/6474772.htm ...

  7. PHP7卓越性能背后的原理有哪些?

    作者:韩天峰链接:http://www.zhihu.com/question/38148900/answer/75115687来源:知乎 PHP7在运行原理上与PHP5相比并没有变化,这与hhvm不同 ...

  8. hihoCoder#1122(二分图最大匹配之匈牙利算法)

    时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上一回我们已经将所有有问题的相亲情况表剔除了,那么接下来要做的就是安排相亲了.因为过年时间并不是很长,所以姑姑希望能够尽可 ...

  9. Java-API-Package:java.lang

    ylbtech-Java-API-Package:java.lang 1.返回顶部 1. Package java.lang Provides classes that are fundamental ...

  10. 如何使用安装光盘为本机创建yum repository

    在CentOS 6上可以使用系统安装光盘为本机创建yum repository,创建过程如下. 创建光盘mount点 [root@centos62 ~]# mkdir /media/CentOS mo ...