RGB565 与 RGB888的相互转换
来源:互联网 发布:c语言char怎么赋值 编辑:程序博客网 时间:2024/05/17 21:37
RGB色彩模式(也翻译为“红绿蓝”,比较少用)是工业界的一种颜色标准,是通过对红(R)、绿(G)、蓝(B)
三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的,RGB即是代表红、绿、蓝三个通道
的颜色,这个标准几乎包括了人类视力所能感知的所有颜色,是目前运用最广的颜色系统之一。
按照上面的图,我们大体知道了 RGB888 -> RGB565是怎么压缩的,也知道了RGB565- > RGB888
是怎么做补偿的,接下来就从代码的角度看看我们具体如何实现这样的转换。
代码:
(rr , gg, bb是属于byte类型,一字节大小)
(1) RGB565 -> RGB888
- <span style="font-size:14px;">rr = byte[1] & 0xf8;
- gg = (byte[1] << 5) | ((byte[0] & 0xe0) >>3);
- bb =byte[0] << 3;
- // 补偿
- rr = rr | ((rr &0x38) >>3);
- gg = gg | ((gg &0x0c) >>2);
- bb = bb | ((bb &0x38) >>3); </span>
另外,也看到了一位大师的两种做法,转自: http://bbs.csdn.net/topics/350153377
(2) RGB888 -> RGB555
- 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
- }
- }
以下是另外的实现方式 ( 注意处理数据的类型)
- #define RGB565_MASK_RED 0xF800
- #define RGB565_MASK_GREEN 0x07E0
- #define RGB565_MASK_BLUE 0x001F
- rgb5652rgb888 :
- unsigned short *pRGB16 = (unsigned short *)lParam;
- for(int i=0; i<176*144; i++)
- {
- unsigned short RGB16 = *pRGB16;
- g_rgbbuf[i*3+2] = (RGB16&RGB565_MASK_RED) >> 11;
- g_rgbbuf[i*3+1] = (RGB16&RGB565_MASK_GREEN) >> 5;
- g_rgbbuf[i*3+0] = (RGB16&RGB565_MASK_BLUE);
- g_rgbbuf[i*3+2] <<= 3;
- g_rgbbuf[i*3+1] <<= 2;
- g_rgbbuf[i*3+0] <<= 3;
- pRGB16++;
- }
另一种:
- rgb5652rgb888(unsigned char *image,unsigned char *image888)
- {
- unsigned char R,G,B;
- B=(*image) & 0x1F;//000BBBBB
- G=( *(image+1) << 3 ) & 0x38 + ( *image >> 5 ) & 0x07 ;//得到00GGGGGG00
- R=( *(image+1) >> 3 ) & 0x1F; //得到000RRRRR
- *(image888+0)=B * 255 / 63; // 把5bits映射到8bits去,自己可以优化一下算法,下同
- *(image888+1)=G * 255 / 127;
- *(image888+2)=R * 255 / 63;
- }
以下来自stackoverflow : http://stackoverflow.com/questions/2442576/how-does-one-convert-16-bit-rgb565-to-24-bit-rgb888
R8 = ( R5 * 527 + 23 ) >> 6;G8 = ( G6 * 259 + 33 ) >> 6;B8 = ( B5 * 527 + 23 ) >> 6;
It uses only: MUL, ADD and SHR -> so it is pretty fast! From the other side it is compatible in 100% to floating point mapping with proper rounding:
// R8 = (int) floor( R5 * 255.0 / 31.0 + 0.5);// G8 = (int) floor( G6 * 255.0 / 63.0 + 0.5);// B8 = (int) floor( R5 * 255.0 / 31.0 + 0.5);
Some extra cents: If you are interested in 888 to 565 conversion, this works very well too:
R5 = ( R8 * 249 + 1014 ) >> 11;G6 = ( G8 * 253 + 505 ) >> 10;B5 = ( B8 * 249 + 1014 ) >> 11;
(这组我看不懂,也没用过,但有人说是可用的,在此转给大家看看)
关于上面按比例转到8 bit的方法 ( 255 / 63 ), 我看到了另外一个实例,也转过来下:
#include <opencv2/core/core.hpp>#include <iostream>using namespace std;using namespace cv;#define RED_MASK 0xF800#define GREEN_MASK 0x07E0#define BLUE_MASK 0x001Fint main(int argc, char* argv[]){ IplImage *rgb565Image = cvCreateImage(cvSize(800, 480), IPL_DEPTH_16U, 1); IplImage *rgb888Image = cvCreateImage(cvSize(800, 480), IPL_DEPTH_8U, 3); unsigned short* rgb565Data = (unsigned short*)rgb565Image->imageData; int rgb565Step = rgb565Image->widthStep / sizeof(unsigned short); uchar* rgb888Data = (uchar*)rgb888Image->imageData; float factor5Bit = 255.0 / 31.0; float factor6Bit = 255.0 / 63.0; for(int i = 0; i < rgb565Image->height; i++) { for(int j = 0; j < rgb565Image->width; j++) { unsigned short rgb565 = rgb565Data[i*rgb565Step + j]; uchar r5 = (rgb565 & RED_MASK) >> 11; uchar g6 = (rgb565 & GREEN_MASK) >> 5; uchar b5 = (rgb565 & BLUE_MASK); // round answer to closest intensity in 8-bit space... uchar r8 = floor((r5 * factor5Bit) + 0.5); uchar g8 = floor((g6 * factor6Bit) + 0.5); uchar b8 = floor((b5 * factor5Bit) + 0.5); rgb888Data[i*rgb888Image->widthStep + j] = r8; rgb888Data[i*rgb888Image->widthStep + (j + 1)] = g8; rgb888Data[i*rgb888Image->widthStep + (j + 2)] = b8; } } return 0;}
以下片段,转自: http://kerlubasola.iteye.com/blog/1579736
- //-------------------------------------------------------------------
- //转换
- staticint rgb565_to_rgb888(constvoid * psrc,int w,int h,void * pdst)
- {
- int srclinesize = UpAlign4(w * 2);
- int dstlinesize = UpAlign4(w * 3);
- const unsignedchar * psrcline;
- const unsignedshort * psrcdot;
- unsignedchar * pdstline;
- unsignedchar * pdstdot;
- int i,j;
- if (!psrc || !pdst || w <= 0 || h <= 0) {
- printf("rgb565_to_rgb888 : parameter error\n");
- return -1;
- }
- psrcline = (const unsigned char *)psrc;
- pdstline = (unsignedchar *)pdst;
- for (i=0; i<h; i++) {
- psrcdot = (const unsigned short *)psrcline;
- pdstdot = pdstline;
- for (j=0; j<w; j++) {
- //565 b|g|r -> 888 r|g|b
- *pdstdot++ = (unsignedchar)(((*psrcdot) >> 0 ) << 3);
- *pdstdot++ = (unsignedchar)(((*psrcdot) >> 5 ) << 2);
- *pdstdot++ = (unsignedchar)(((*psrcdot) >> 11) << 3);
- psrcdot++;
- }
- psrcline += srclinesize;
- pdstline += dstlinesize;
- }
- return 0;
- }
- staticint rgb888_to_rgb565(constvoid * psrc,int w,int h,void * pdst)
- {
- int srclinesize = UpAlign4(w * 3);
- int dstlinesize = UpAlign4(w * 2);
- const unsignedchar * psrcline;
- const unsignedchar * psrcdot;
- unsignedchar * pdstline;
- unsignedshort * pdstdot;
- int i,j;
- if (!psrc || !pdst || w <= 0 || h <= 0) {
- printf("rgb888_to_rgb565 : parameter error\n");
- return -1;
- }
- psrcline = (const unsigned char *)psrc;
- pdstline = (unsignedchar *)pdst;
- for (i=0; i<h; i++) {
- psrcdot = psrcline;
- pdstdot = (unsignedshort *)pdstline;
- for (j=0; j<w; j++) {
- //888 r|g|b -> 565 b|g|r
- *pdstdot = (((psrcdot[0] >> 3) & 0x1F) << 0)//r
- |(((psrcdot[1] >> 2) & 0x3F) << 5)//g
- |(((psrcdot[2] >> 3) & 0x1F) << 11);//b
- psrcdot += 3;
- pdstdot++;
- }
- psrcline += srclinesize;
- pdstline += dstlinesize;
- }
- return 0;
- }
- RGB565 与 RGB888的相互转换
- RGB565 与 RGB888的相互转换
- rgb888与rgb565转换的影响
- RGB565和RGB888的转换
- RGB565 与RGB888的区别
- RGB888和RGB565互相转换
- RGB565,RGB555, RGB888,RGB32转换
- RGB565 & RGB888
- RGB888->RGB565
- RGB888->RGB565
- RGB888->RGB565
- RGB565,RGB888
- RGB888->RGB565
- RGB888转换为RGB565颜色值
- RGB888->RGB565->RGB888
- 一组rgb转换函数,支持rgb565/rgb888/xrgb8888之间的数据转换
- Mini2440之LCD的RGB888和RGB565
- RGB888和565相互转换
- android配置adb
- rr公司的一道面试题
- 图片缓存之内存缓存技术LruCache
- 承诺,项目管理中的大杀器
- VS下创建网站发布到IIS
- RGB565 与 RGB888的相互转换
- C#中如何获取当前路径的几种方法
- YUV RGB 转换
- Spring JdbcTemplate方法详解
- 一个snprintf函数format参数的问题
- Gartner预测2015年的十大IT战略发展趋势
- STL之优先队列
- java入门-标示符与关键字和基本数据类型
- Android JNI使用方法(“动态注册”)