1、为什么RGB888要转RGB565呢,这个问题尤其在嵌入式lcd屏中,因为RGB888占用24位,RGB565占用16位及2个字节。
2、例如嵌入式中的LCD屏接口一般位IIC、SPI、8080等,如果传送RGB888每个像素点就要多送一个字节,320*240的LCD屏就要多送76800字节的数据。
3、我看到的一般驱动代码中均是将RGB888进行相与移位等操作得到R,G、B类似操作。速度慢代码不精简。如何优化呢,这里我就开门见山了,使用结构体就能很好解决RGB888和RGB565互转。单使用结构体还不够好,就把结构体和共用体结合了。
4、以下是测试部分,使用原始方案RGB888转RGB565,及原始方案RGB565转RGB888,及新的方案。不难发现新方案测试结果和旧方案一样。
5、最后贴出具体代码,当前使用的是小端模式,切记51单片机一般位大端模式。
//作者:金丝草
//时间:2022/09/24
#include <iostream>
//这里重申下,以下为小端模式
/***********************************RGB888 RGB565*************************************/
typedef union
{
uint32_t RGB888;
struct
{
uint32_t dummy0:3;
uint32_t RGB_B :5;
uint32_t dummy1:2;
uint32_t RGB_G :6;
uint32_t dummy2:3;
uint32_t RGB_R :5;
uint32_t dummy3:8;
}Work;
}RGB888_struct;
typedef union
{
uint16_t RGB565;
struct
{
uint16_t RGB_B :5;
uint16_t RGB_G :6;
uint16_t RGB_R :5;
}Work;
}RGB565_struct;
//输入一个RGB888的32位数据地址,返回转换后的RGB565
static uint16_t RGB888_To_RGB565(const RGB888_struct *RGB888)
{
RGB565_struct RGB565 = { 0 };
RGB565.Work.RGB_R = RGB888->Work.RGB_R;
RGB565.Work.RGB_G = RGB888->Work.RGB_G;
RGB565.Work.RGB_B = RGB888->Work.RGB_B;
return RGB565.RGB565;
}
//输入一个RG565的16位数据地址,返回转换后的RGB888
static uint32_t RGB565_To_RGB888(const RGB565_struct *RGB565)
{
RGB888_struct RGB888 = { 0 };
RGB888.Work.RGB_R = RGB565->Work.RGB_R;
RGB888.Work.RGB_G = RGB565->Work.RGB_G;
RGB888.Work.RGB_B = RGB565->Work.RGB_B;
return RGB888.RGB888;
}
/***********************************RGB888 RGB565*************************************/
static void test_RGB888_To_RGB565(void)
{
uint32_t color888 = 0;
uint32_t i;
for (i = 1; i <= 50; i++)
{
printf("RGB888->RGB565 =%5d ", RGB888_To_RGB565((RGB888_struct*)&color888));
color888 += 100;
if ((i % 5) == 0)
printf("\r\n");
}
printf("\r\n");
}
static void test_RGB565_To_RGB888(void)
{
uint16_t color565 = 0;
uint32_t i;
for (i = 1; i <= 50; i++)
{
printf("RGB565->RGB888 =%7d ", RGB565_To_RGB888((RGB565_struct*)&color565));
color565 += 100;
if((i%5) == 0)
printf("\r\n");
}
printf("\r\n");
}
int main()
{
uint32_t test_data = 0;
uint32_t i;
uint32_t color888 = 0;
uint16_t color565 = 0;
uint8_t R = 0;
uint8_t G = 0;
uint8_t B = 0;
for (i = 1; i <= 50; i++)//原始方案计算伤脑子
{
R = (color888 & 0xff0000) >> (16 + 3);
G = (color888 & 0x00ff00) >> (8 + 2);
B = (color888 & 0x0000ff) >> 3;
test_data = (R << (5 + 6)) | (G << 5) | B;
printf("test__888->565 =%5d ", test_data);
color888 += 100;
if ((i % 5) == 0)
printf("\r\n");
}
printf("\r\n");
test_RGB888_To_RGB565();//新方案速度更快还不伤脑子
for (i = 1; i <= 50; i++)//原始方案计算伤脑子
{
R = (color565 & 0xf800) >> (5 + 6);
G = (color565 & 0x07e0) >> 5;
B = (color565 & 0x001f) >> 0;
test_data = (R << (16 + 3)) | (G << 8 + 2) | (B << 3);
printf("test__565->888 =%7d ", test_data);
color565 += 100;
if ((i % 5) == 0)
printf("\r\n");
}
printf("\r\n");
test_RGB565_To_RGB888();//新方案速度更快还不伤脑子
std::cout << "Hello World!\n";
}