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

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 B0

1.取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 B0

16bit 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 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

说明:第二行的 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)

{

java rgb565转rgb888_RGB565 与 RGB888的相互转换 | 学步园相关推荐

  1. java阿拉伯转大写_java 中大写数字与阿拉伯数之间的相互转换 | 学步园

    public class CNNumberFormat { private static final char []cnNumbers={'零', '壹', '贰', '叁', '肆', '伍','陆 ...

  2. java构造字符缓冲区_java学习笔记 | 学步园

    一.数组 类型[] 名称=new 类型[长度] 二.字符串2.1字符串类Stringjava.lang.StringString 名称=new String("xxxx")=&qu ...

  3. java ipv6校验_JS及java验证 IPV6,IPV4地址的 正则表达式 | 学步园

    JS 验证: ipv4地址验证: function queryDev(ip){ var exp=/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2 ...

  4. liunx java font_Linux下JDK中文字体乱码 | 学步园

    问题描述: 部署在linux下的java应用程序中的中文会变成一个一个的"口"字,也就是乱码 问题分析: 代码中使用了如下的实现方式: newjava.awt.Font(" ...

  5. java生成密码_java生成密码生成 | 学步园

    一.根据当前日期生成MD5加密密码 package com.test; import java.security.MessageDigest; import java.text.SimpleDateF ...

  6. java 负数存储结构_负数在java中的存储和读取过程 | 学步园

    问题描述: 将-5存储在文本文件中,再读取出来显示到控制台; 预备知识: 1.在java中使用补码处理数字,而且byte(8)的数字在扩展成int(32)类型的时候,正数填充0,负数填充1; 2.负数 ...

  7. java压缩成.tar_java压缩tar.gz | 学步园

    zlib.gzip.zip这三个概念的确比较容易混淆: zlib是一种数据压缩程序库,它的设计目标是处理单纯的数据(而不管数据的来源是什么). gzip是一种文件压缩工具(或该压缩工具产生的压缩文件格 ...

  8. java gnu_GNU/Linux下Java开发环境的安装和配置 | 学步园

    首先下载JDK,在http://www.oracle.com/technetwork/java/javase/downloads/index.html下载最新版本的JDK,选择平台为linux,就会得 ...

  9. java 读取csv_Java读取CSV的常用方法 | 学步园

    在项目开发中,我们经常需要读取csv的内容的操作.读取的逻辑并不复杂.主要是对有换行的,逗号,引号的处理恰当的话就没问题了. 下面作为memo,把在项目中的读取方法拷贝了过来.有了下面的这些方法,在C ...

  10. java classpath bat_tomcat启动批处理——setclasspath.bat | 学步园

    除了上面两个批处理,还有一个比较重要的脚本,即是setclasspath.bat,它主要负责寻找.检查JAVA_HOME和JRE_HOME两个变量. ************************* ...

最新文章

  1. mysql字节对齐_结构体字节对齐-位域及其对齐
  2. Seata 单机环境搭建_01
  3. java程序单引号报错,javapoigetInpuStream报错br/是这样的, 爱问知识人
  4. 《Windows驱动开发技术详解》之HelloDDK
  5. 有头结点单链表的逆置
  6. oracle:10g下载地址(转载)
  7. 企业常用的站内收索、QQ群、在线客服
  8. Mantis1.2.19 在Windows 平台上的安装配置详解
  9. Vivado下使用Microblaze控制LED(vcu118,HLS级开发)
  10. 『码上行动-编程擂台』学员作品展(附源码)
  11. 蚂蚁金服前端实习生二面面经
  12. 股票价格与采购经理人指数(PMI) 之间的关系
  13. SICP 第二章的练习
  14. flink报错:The types of the interface org.apache.flink.util.OutputTag could not be inferred.
  15. mos 多路模拟电子开关_模拟开关与多路转换器
  16. one 主格 复数 宾格_主格、宾格、名词所有格
  17. Java【汉诺塔问题】详细图文解析, 包教包会
  18. 顺丰bsp系统 java_顺丰BSP接口SOAP的请求示例
  19. 计算机网络 -- RS232接口 ----OSI物理层协议----RS232接口
  20. 4-AMBA VIP 编程接口

热门文章

  1. lenovo L480 进入bios_联想笔记本BIOS升级教程
  2. 阿铭Linux_总览部分学习笔记20190114
  3. java 过滤 rtf 图片_忽略WPF RichTextBox中RTF文件中图像的定位
  4. 010Editor查看PE文件
  5. 近期14个“AI产品经理”职位JD推荐(覆盖北京、上海、深圳、成都、重庆、杭州)
  6. 【信息汇总】北京航空航天大学计算机考研
  7. 华为HG8245光纤猫获得超级用户密码
  8. 安卓问题-第三方相关
  9. 如何下载无水印的抖音视频?
  10. itchat使用教程