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, , 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的转换的更多相关文章
- RGB565 转换 BMP24
今晚有心情,就做完了BMP16(RGB565) 转换成BMP24 的小程序.其中最关键的地方是: // k,WORD类型,是RGB565 的一个点的数据(可以认为是灰度). r=(k & 0x ...
- RGB888->RGB565->RGB888
转自CB的博客:http://blog.chinaaet.com/detail/28298 在我们的计算机中,图像是以RGB888显示的,24位图每个像素保存了32bit的数据,即RGB888+Al ...
- 关于yuv 的pack(紧缩格式)和planner(平面格式)格式 [转]
关于yuv 格式 YUV 格式通常有两大类:打包(packed)格式和平面(planar)格式.前者将 YUV 分量存放在同一个数组中,通常是几个相邻的像素组成一个宏像素(macro-pixel);而 ...
- YUV422 YUV420 Planar \ Semi-Planar \ Interleaved
关于yuv 格式 YUV 格式通常有两大类:打包(packed)格式和平面(planar)格式.前者将 YUV 分量存放在同一个数组中,通常是几个相邻的像素组成一个宏像素(macro-pixel);而 ...
- 基于FPGA的彩色图像转灰度算法实现
昨天才更新了两篇博客,今天又要更新了,并不是我垃圾产,只不过这些在上个月就已经写好了,只是因为比赛忙,一直腾不出时间整理出来发表而已,但是做完一件事情总感觉不写一博文总结一下就少点什么,所以之后的一段 ...
- 基于FPGA的RGB565_YCbCr_Gray算法实现
前面我们讲了基于FPGA用VGA显示一副静态图片,那么接下来我们就接着前面的工程来实现我们图像处理的基础算法里最简单的一个那就是彩色图像转灰度的实现. 将彩色图像转化为灰度的方法有两种,一个是令RGB ...
- ILI9341液晶显示
17.1液晶显示原理 TFT-LCD(Thin Film Transistor Liquid Crystal Display)即薄膜晶体管液晶显示器,是微电子技术与液晶显示器技术巧妙结合的的一种技术. ...
- YUV到RGB的转换
以下内容来源于网络,下面三个链接里的内容是比较好的,感谢博主的分享. http://blog.csdn.net/housisong/article/details/1859084 http://blo ...
- YUV / RGB 格式及快速转换算法
1 前言 自然界的颜色千变万化,为了给颜色一个量化的衡量标准,就需要建立色彩空间模型来描述各种各样的颜色,由于人对色彩的感知是一个复杂的生理和心理联合作用 的过程,所以在不同的应用领域中为了更好更准确 ...
随机推荐
- BZOJ4808: 马
BZOJ4808: 马 https://lydsy.com/JudgeOnline/problem.php?id=4808 分析: 黑白染色,求二分图最大匹配即可. 代码: #include < ...
- LoadRunner常见错误代码解决方案
一.LoadRunner26377错误 通常不是长度的问题,如果长度有问题就都出错了.应该是服务器返回的数据问题,导致没有找到这个参数. 26377错误的成因很多,总结最直接的结果就是No match ...
- 感知机学习算法Java实现
感知机学习算法Java实现. Perceptron类用于实现感知机, 其中的perceptronOriginal()方法用于实现感知机学习算法的原始形式: perceptronAnother()方法用 ...
- springboot springcloud eureka
参考: https://www.cnblogs.com/skyblog/p/5133752.htmlhttp://blog.csdn.net/u012734441/article/details/78 ...
- Linux网络工具lsof和netstat
lsof全名为list opened files,即列举系统中已经被打开的文件,基本使用如下: (1) 查看/etc/passwd使用情况 lsof /etc/password (2) 查看监听的so ...
- system中有空格怎么办
原始路径: C:\\Program Files\\putty\\putty.exe 改为: char *cmd="C:\\\"Program Files\"\\putty ...
- spring的配置文件在web.xml中加载的方式
web.xml加载spring配置文件的方式主要依据该配置文件的名称和存放的位置不同来区别,目前主要有两种方式. 1.如果spring配置文件的名称为applicationContext.xml,并且 ...
- mysql如何开启远程连接(默认未开启,即使密码正确,仍然无法访问)
mysql如何开启远程连接 | 浏览:1846 | 更新:2015-03-11 20:19 1 2 3 4 5 6 分步阅读 百度经验:jingyan.baidu.com 大家在公司工作中,经常会遇到 ...
- mui封装的ajax请求
由于项目中引进MUI框架,所以就不需要引进jquery,但需要和后台交互时,常写为jquery格式:所以笔者觉得有必要将mui封装的ajax请求在这里提一下: 1,mui框架基于htm5plus的XM ...
- ListView显示Sqlite的数据
在安卓中,ListView和Sqlite都是十分常用的.这次我们来结合这个两个知识点写一个Demo. 功能:吧SQLite中的数据用ListView显示出来. 先看截图吧 首先是数据库 然后是运行截图 ...