java rgb565转rgb888_RGB565 与 RGB888的相互转换

本文内容不是完全原创,参考了网上部分精华,做了整理。

RGB色彩模式(也翻译为“红绿蓝”,比较少用)是工业界的一种颜色标准,是通过对红(R)、绿(G)、蓝(B)

三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的,RGB即是代表红、绿、蓝三个通道

的颜色,这个标准几乎包括了人类视力所能感知的所有颜色,是目前运用最广的颜色系统之一。

就RGB888->RGB565而言:其转换的具体思路如下:(注:只代表个人的方法)1.取RGB888中第一个字节的高5位作为转换后的RGB565的第二个字节的高5位2.取RGB888中第二个字节的高3位作为转换后的RGB565第二个字节的低3位3.取RGB888中第二个字节的第4--6位,作为转换后的RGB565第一个字节的高3位4.取RGB888中第二个字节的第三个字节的高5位作为转换后的RGB565第一个字节的低5位就RGB565->RGB888而言:RGB565的存储方式为:R4 R3 R2 R1 R0 G5 G4 G3 G2 G1 G0 B4 B3 B2 B1 B01.取RGB565第一个字节中低5位作为RGB888的高5位2.取RGB565第二个字节中的低3位,将其左移5位,作为RGB888第二个字节的高5位3.取RGB565第一个字节的高3位将其右移3位,作为RGB888第二个字节的4--6位4.取RGB565第二个字节中的高5位作为RGB888第三个字节。

细心地哥们一定会发现如果我们是低位往高位上转的话,就存在一些数据精度的丢失问题,

在网上查了写资料,借鉴了一下别人的方法;所谓的量化补偿,讲一下量化压缩与量化补偿吧

在进行色彩格式转换的时候,经常会遇到色彩量化位数的改变,比如说从 24bit RGB888

到 16bit RGB565 的色彩转换。所谓量化压缩与量化补偿都是我个人所提出的概念,现说明如下。

量化压缩,举例:

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 B016bit RGB656 R7 R6 R5 R4 R3 G7 G6 G5 G4 G3 G2 B7 B6 B5 B4 B3量化位数从8bit到5bit或6bit,取原8bit的高位,量化上做了压缩,却损失了精度。量化补偿,举例:     16bit RGB565 -> 24bit RGB888 的转换16bit RGB656 R4 R3 R2 R1 R0 G5 G4 G3 G2 G1 G0 B4 B3 B2 B1 B024ibt RGB888 R4 R3 R2 R1 R0 0 0 0 G5 G4 G3 G2 G1 G0 0 0 B4 B3 B2 B1 B0 0 0 024ibt 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

说明:第二行的 24bit RGB888 数据为转换后,未进行补偿的数据,在精度上会有损失第三行的 24bit RGB888 数据为经过量化补偿的数据,对低位做了量化补偿可以很容易的证明,这样的补偿方法是一种合理的线性补偿。补偿的原理很简单,大家仔细想一下就明白了,因此不再详细说明。总结一下:量化压缩的方法:三个字取高位量化补偿的方法:1. 将原数据填充至高位2. 对于低位,用原始数据的低位进行补偿3. 如果仍然有未填充的位,继续使用原始数据的低位进行循环补偿

按照上面的图,我们大体知道了 RGB888 -> RGB565是怎么压缩的,也知道了RGB565- > RGB888

是怎么做补偿的,接下来就从代码的角度看看我们具体如何实现这样的转换。

代码:

(rr , gg, bb是属于byte类型,一字节大小)

(1) RGB565 -> RGB888

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); 

(2) RGB888 -> RGB555

for(intj = 0; j 

{

WORD*pTemp = (WORD*)(pData + WIDTHBYTES(bmih.biWidth * 16) * j);

for(inti = 0; i 

{

#if 1

*pTemp++ = ((WORD)(*pR++ <> 3) & 0x001f);

#else

intnR = (*pR++ + 4) >> 3;

intnG = (*pG++ + 2) >> 2;

intnB = (*pB++ + 4) >> 3;

if(nR > 31) nR = 31;

if(nG > 63) nG = 63;

if(nB > 31) nB = 31;

*pTemp++ = (nR <

#endif

}

}

以下是另外的实现方式 ( 注意处理数据的类型)

#define RGB565_MASK_RED 0xF800

#define RGB565_MASK_GREEN 0x07E0

#define RGB565_MASK_BLUE 0x001F

rgb5652rgb888 :

unsigned short*pRGB16 = (unsignedshort*)lParam;

for(inti=0; i<176*144; i++)

{

unsigned shortRGB16 = *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(unsignedchar*image,unsignedchar*image888)

{

unsigned charR,G,B;

B=(*image) & 0x1F;//000BBBBB

G=( *(image+1) <> 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;

}

本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。

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

#include

using namespace std;

using namespace cv;

#define RED_MASK 0xF800

#define GREEN_MASK 0x07E0

#define BLUE_MASK 0x001F

int 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;

}

//-------------------------------------------------------------------

//转换

staticintrgb565_to_rgb888(constvoid* psrc,intw,inth,void* pdst)

{

intsrclinesize = UpAlign4(w * 2);

intdstlinesize = UpAlign4(w * 3);

constunsignedchar* psrcline;

constunsignedshort* psrcdot;

unsigned char* pdstline;

unsigned char* pdstdot;

inti,j;

if(!psrc || !pdst || w <= 0 || h <= 0) {

printf("rgb565_to_rgb888 : parameter error\n");

return-1;

}

psrcline = (constunsignedchar*)psrc;

pdstline = (unsigned char*)pdst;

for(i=0; i

psrcdot = (constunsignedshort*)psrcline;

pdstdot = pdstline;

for(j=0; j

//565 b|g|r -> 888 r|g|b

*pdstdot++ = (unsigned char)(((*psrcdot) >> 0 ) <

*pdstdot++ = (unsigned char)(((*psrcdot) >> 5 ) <

*pdstdot++ = (unsigned char)(((*psrcdot) >> 11) <

psrcdot++;

}

psrcline += srclinesize;

pdstline += dstlinesize;

}

return0;

}

staticintrgb888_to_rgb565(constvoid* psrc,intw,inth,void* pdst)

{

intsrclinesize = UpAlign4(w * 3);

intdstlinesize = UpAlign4(w * 2);

constunsignedchar* psrcline;

constunsignedchar* psrcdot;

unsigned char* pdstline;

unsigned short* pdstdot;

inti,j;

if(!psrc || !pdst || w <= 0 || h <= 0) {

printf("rgb888_to_rgb565 : parameter error\n");

return-1;

}

psrcline = (constunsignedchar*)psrc;

pdstline = (unsigned char*)pdst;

for(i=0; i

psrcdot = psrcline;

pdstdot = (unsigned short*)pdstline;

for(j=0; j

//888 r|g|b -> 565 b|g|r

*pdstdot =  (((psrcdot[0] >> 3) & 0x1F) <

|(((psrcdot[1] >> 2) & 0x3F) <

|(((psrcdot[2] >> 3) & 0x1F) <

psrcdot += 3;

pdstdot++;

}

psrcline += srclinesize;

pdstline += dstlinesize;

}

return0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于C++&OPENCV 的全景图像拼接 C++是一种广泛使用的编程语言,它是由Bjarne Stroustrup于1979年在新泽西州美利山贝尔实验室开始设计开发的。C++是C语言的扩展,旨在提供更强大的编程能力,包括面向对象编程和泛型编程的支持。C++支持数据封装、继承和多态等面向对象编程的特性和泛型编程的模板,以及丰富的标准库,提供了大量的数据结构和算法,极大地提高了开发效率。12 C++是一种静态类型的、编译式的、通用的、大小写敏感的编程语言,它综合了高级语言和低级语言的特点。C++的语法与C语言非常相似,但增加了许多面向对象编程的特性,如类、对象、封装、继承和多态等。这使得C++既保持了C语言的低级特性,如直接访问硬件的能力,又提供了高级语言的特性,如数据封装和代码重用。13 C++的应用领域非常广泛,包括但不限于教育、系统开发、游戏开发、嵌入式系统、工业和商业应用、科研和高性能计算等领域。在教育领域,C++因其结构化和面向对象的特性,常被选为计算机科学和工程专业的入门编程语言。在系统开发领域,C++因其高效性和灵活性,经常被作为开发语言。游戏开发领域中,C++由于其高效性和广泛应用,在开发高性能游戏和游戏引擎中扮演着重要角色。在嵌入式系统领域,C++的高效和灵活性使其成为理想选择。此外,C++还广泛应用于桌面应用、Web浏览器、操作系统、编译器、媒体应用程序、数据库引擎、医疗工程和机器人等领域。16 学习C++的关键是理解其核心概念和编程风格,而不是过于深入技术细节。C++支持多种编程风格,每种风格都能有效地保证运行时间效率和空间效率。因此,无论是初学者还是经验丰富的程序员,都可以通过C++来设计和实现新系统或维护旧系统。3

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值