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 前言 自然界的颜色千变万化,为了给颜色一个量化的衡量标准,就需要建立色彩空间模型来描述各种各样的颜色,由于人对色彩的感知是一个复杂的生理和心理联合作用 的过程,所以在不同的应用领域中为了更好更准确 ...
随机推荐
- P1230 智力大冲浪(洛谷)
题目描述 小伟报名参加中央电视台的智力大冲浪节目.本次挑战赛吸引了众多参赛者,主持人为了表彰大家的勇气,先奖励每个参赛者m元.先不要太高兴!因为这些钱还不一定都是你的?!接下来主持人宣布了比赛规则: ...
- jQuery.extend()方法
定义和用法 jQuery.extend()函数用于将一个或多个对象的内容合并到目标对象. 注意: 1. 如果只为$.extend()指定了一个参数,则意味着参数target被省略.此时,target就 ...
- 增加 [确定] and [失败]系统提示
增加 [确定] and [失败]系统提示 #!/bin/bash. /etc/init.d/functionsaction "true" /bin/falseaction &qu ...
- Asp.net工作流workflow实战之工作流持久化(五)
直接看msdn https://msdn.microsoft.com/zh-cn/library/ee395773(v=vs.100).aspx
- microsoft windows network 不允许一个用户使用一个以上用户名与服务器或共享资源的多重连接
运行CMD在命令行中运行net use * /del /y 命令中断开所有连接最后,你再次访问 ,就不会有问题了. 而且可以连接多个samba用户.
- openwrt 按下回车才能显示图标信息
如题所示,openwrt启动后,手动才能按下系统图标和信息. 如何却掉这个手动选项呢? 修改文件/SISP-L26.7.8-OpenWrt/build_dir/target-arm_uClibc-0. ...
- 分析诊断工具之五:Procedure Analyse优化表结构
一.Procedure Analyse PROCEDURE ANALYSE() ,在优化表结构时可以辅助参考分析语句.通过分析select查询结果对现有的表的每一列给出优化的建议. 利用此语句,MyS ...
- $route路由
<!DOCTYPE html><html ng-app="AngularApp"> <head> <meta charset=" ...
- 转:InnoDB Log Block Structure(InnoDB日志Block结构详解)
文章转载自等博 InnoDB Log Block Structure(InnoDB日志Block结构详解)
- iOS消息转发机制
iOS消息转发机制 “消息派发系统”(message-dispatch system) 若想令类能够理解某条消息,我们必须实现出对应的方法才行.但是,在编译器向类发送其无法解读的消息时并不会报错,因为 ...