嵌入式软件导论大作业
大作业:RGB格式转换的实现
指导教师:XXX
    院:软件学院
    级:XXX                 
    号:XXX
    名:XXX

大作业:RGB格式转换的实现
1RGB888 RGB565 两种格式存储特点
2RGB565获取每一个分量的数据值的实现写出来。
3RGB888565的实现函数
4565888的实现函数(中间的颜值是有精度损失、最终的颜值经过量化补偿的操作)
5、实现一个完整的测试程序
linux平台下面通过打开bmp图片的方式,利用之前实现的函数对其格式进行转换,把最终转换的图片颜数据输出出来

1.RGB888 RGB565 两种格式存储特点
真彩是指图像中的每个像素值都分成R(红)、G(绿)、B(蓝)三个基分量,每个基分量直接决定其基的强度,这样产生的彩称为彩。彩图像是一种用三个或更多字节描述像素的计算机图像存储方式。 普遍认为人眼对彩的分辨能力大致是一千万,因此由RGB888形成的图像称做真彩。RGB888真彩,每一光以8位元表示,每个通道各有256级阶调,三光交互增减,RGB三光能在一个像素上最高显示24位1677万(256*25
6*256=16,777,216),这个数值就是电脑所能表示的最高彩。RGB332(3+3+2=8位):(2^3)*(2^3)*(2^2)=8*8*4=256(256 Color)。俗称256RGB555(5+5+5=15位):(2^5)*(2^5)*(2^5)=32*32*32=32768(32768/1024=32, 32K Color)。俗称32千RGB565(5+6+5=16位):(2^5)*(2^6)*(2^5)=32*64*32=65536(65536/1024=32, 64K Color)。俗称65千RGB666(6+6+6=18位):(2^6)*(2^6)*(2^6)=64*64*64=262144(262144/1024=256, 256K Color)。俗称262千RGB888(8+8+8=24位):(2^8)*(2^8)*(2^8)=256*256*256=16777216(16777216/1024=16384, 16384K Color; 16384/1024=16, 16M Color)。俗称16兆真彩RGB888+8(8+8+8+8=32位):
RGB565彩模式, 一个像素占两个字节, 其中:
低字节的前5位用来表示B(BLUE)
字节的后三位+高字节的前三位用来表示G(Green)
高字节的后5位用来表示R(RED)
在进行彩格式转换的时候,经常会遇到彩量化位数的改变,比如说从 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. 如果仍然有未填充的位,继续使用原始数据的低位进行循环补偿
  解释一下循环补偿的概念:
  8bit RGB332 -> 24bit RGB888 的转换
  8bit RGB332 R2 R1 R0 G2 G1 G0 B1 B0
  24bit RGB888 R2 R1 R0 0 0 0 0 0 G2 G1 G0 0 0 0 0 0 B1 B0 0 0 0 0 0 0
  24bit RGB888 R2 R1 R0 R2 R1 R0 0 0 G2 G1 G0 G2 G1 G0 0 0 B1 B0 B1 B0 0 0 0 0
  24bit RGB888 R2 R1 R0 R2 R1 R0 R2 R1 G2 G1 G0 G2 G1 G0 G2 G1 B1 B0 B1 B0 B1 B0 0 0
  24bit RGB888 R2 R1 R0 R2 R1 R0 R2 R1 G2 G1 G0 G2 G1 G0 G2 G1 B1 B0 B1 B0 B1 B0 B1 B0
2. RGB565获取每一个分量的数据值的实现
rgb24[2] = (rgb565 & RGB565_MASK_RED) >> 11;   
    rgb24[1] = (rgb565 & RGB565_MASK_GREEN) >> 5; 
    rgb24[0] = (rgb565 &  RGB565_MASK_BLUE); 
3.RGB888565的实现函数
RGB888RGB565的实现方式
unsigned short rgb_24_to_565(unsigned short r, unsigned short g, unsigned short b) 
        return ((r << 8) & 0xF800) | ((g << 3) & 0x07E0) | ((b >> 3) & 0x001f);
}
4.565888的实现函数
    void rgb565_to_rgb24(BYTE *rgb24, unsigned short rgb565) 
    //extract RGB 
rgb24[2] = (rgb565 & RGB565_MASK_RED) >> 11;   
    rgb24[1] = (rgb565 & RGB565_MASK_GREEN) >> 5; 
    rgb24[0] = (rgb565 &  RGB565_MASK_BLUE); 
//amplify the image 
    rgb24[2] <<= 3; 
    rgb24[1] <<= 2; 
    rgb24[0] <<= 3;
    rgb24[2] = rgb24[2] | ((rgb24[2] & 0x38) >> 3);
    rgb24[1] = rgb24[1] | ((rgb24[1] & 0x0c) >> 2)
    rgb24[0] = rgb24[0] | ((rgb24[0] & 0x38) >> 3);
}
5、实现一个完整的测试程序
printf输出格式linux#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define RGB565_MASK_RED        0xF800 
#define RGB565_MASK_GREEN      0x07E0 
#define RGB565_MASK_BLUE      0x001F 
#pragma pack(2)
/*定义WORD为两个字节的类型*/
typedef unsigned short WORD;
/*定义DWORD为e四个字节的类型*/
typedef unsigned long DWORD;
typedef char BYTE;
/*位图文件头*/
typedef struct BMP_FILE_HEADER
{
    WORD bType; /* 文件标识符 */
    DWORD bSize; /* 文件的大小 */
    WORD bReserved1; /* 保留值,必须设置为0 */
    WORD bReserved2; /* 保留值,必须设置为0 */
    DWORD bOffset; /* 文件头的最后到图像数据位开始的偏移量 */
} BMPFILEHEADER;
/*位图信息头*/
typedef struct BMP_INFO
{
    DWORD bInfoSize; /* 信息头的大小 */
    DWORD bWidth; /* 图像的宽度 */
    DWORD bHeight; /* 图像的高度 */
    WORD bPlanes; /* 图像的位面数 */
    WORD bBitCount; /* 每个像素的位数 */
    DWORD bCompression; /* 压缩类型 */
    DWORD bmpImageSize; /* 图像的大小,以字节为单位 */
    DWORD bXPelsPerMeter; /* 水平分辨率 */
    DWORD bYPelsPerMeter; /* 垂直分辨率 */
    DWORD bClrUsed; /* 使用的彩数 */
    DWORD bClrImportant; /* 重要的颜数 */
} BMPINF;
unsigned short rgb_24_to_565(int r, int g, int b){
    return (unsigned short)((((unsigned)r<<8)&0xF800) |    (((unsigned)g<<3)&0x7E0) |    (((unsigned)b>>3)));
}
void rgb565_to_rgb24(BYTE *rgb24, unsigned short rgb565) 
    //extract RGB  分离出RGB
    rgb24[2] = (rgb565 & RGB565_MASK_RED) >> 11;