如何将GIMP导出的RGB565格式C源码图像转换为RGB888?
RGB565转RGB888转换结果不符的问题排查
我使用GIMP生成了如下C源码图像dump:
/* GIMP RGBA C-Source image dump (example.c) */ static const struct { guint width; guint height; guint bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */ guint8 pixel_data[304 * 98 * 2 + 1]; } example= { 304, 98, 2, "\206\061\206\061....." };
我希望将该图像从RGB565格式转换为RGB888格式,尝试了以下逐像素转换代码:
for (i = 0; i < w * h; i++) { uint16_t color = *RGB565p++; uint8_t r = ((color >> 11) & 0x1F); uint8_t g = ((color >> 5) & 0x3F); uint8_t b = (color & 0x1F); r = ((((color >> 11) & 0x1F) * 527) + 23) >> 6; g = ((((color >> 5) & 0x3F) * 259) + 33) >> 6; b = (((color & 0x1F) * 527) + 23) >> 6; uint32_t RGB888 = r << 16 | g << 8 | b; printf("%d \n", RGB888); }
但使用该逻辑得到的数值与原图像的表示不符,输出如下:
P3 304 98 255 3223857 3223857 3223857 3223857 3223857 3223857 3223857 3223857
问题原因及修正方案
字节序不匹配:GIMP生成的RGB565数据采用大端字节序(高字节在前),但你的代码直接通过
uint16_t指针读取,会按照当前系统的字节序(通常是小端)解析,导致颜色值完全错误。比如dump里的"\206\061"是十进制134和49,大端组合应为134<<8 | 49 = 34361,小端读取则是49<<8 |134=12618,这会让所有像素解析成同一种颜色。
修正:手动按大端拼接字节:uint8_t byte1 = *RGB565p++; uint8_t byte2 = *RGB565p++; uint16_t color = (byte1 << 8) | byte2;输出格式错误:你输出的是合并后的32位RGB888整数,但P3格式的PPM要求输出每个通道的单独数值(红、绿、蓝各占一行或同一行),而非合并值。这也是为什么你看到的全是重复的整数——实际是同一个颜色的合并值。
修正:输出三个通道的独立值:printf("%d %d %d\n", r, g, b);冗余代码:代码中先给r、g、b赋值了一次原始通道值,随后又重新计算覆盖,这部分冗余代码可以直接删除,不影响功能。
修正后的完整代码示例
for (i = 0; i < w * h; i++) { // 按大端读取GIMP生成的RGB565像素 uint8_t byte1 = *RGB565p++; uint8_t byte2 = *RGB565p++; uint16_t color = (byte1 << 8) | byte2; // 转换为RGB888 uint8_t r = ((((color >> 11) & 0x1F) * 527) + 23) >> 6; uint8_t g = ((((color >> 5) & 0x3F) * 259) + 33) >> 6; uint8_t b = (((color & 0x1F) * 527) + 23) >> 6; // 符合P3格式的输出 printf("%d %d %d\n", r, g, b); }
内容的提问来源于stack exchange,提问作者navy1978
相关产品推荐
相关产品推荐

