我已经拿到了 16 位 rgb565 图像(特别是 Android 帧缓冲区转储),我想将其转换为 24 位 rgb888,以便在普通显示器上查看。
问题是,如何将 5 位或 6 位通道转换为 8 位通道?显而易见的答案是改变它。我一开始是这样写的:
puts("P6 320 480 255");
uint16_t buf;
while (read(0, &buf, sizeof buf)) {
unsigned char red = (buf & 0xf800) >> 11;
unsigned char green = (buf & 0x07e0) >> 5;
unsigned char blue = buf & 0x001f;
putchar(red << 3);
putchar(green << 2);
putchar(blue << 3);
}
然而,这没有一个我想要的属性,即0xffff
映射到0xffffff
, 代替0xf8fcf8
。我需要以某种方式扩大价值,但我不确定这应该如何运作。
Android SDK 附带了一个名为 ddms(Dalvik 调试监视器)的工具,可以捕获屏幕截图。据我所知阅读代码,它实现了相同的逻辑;但它的屏幕截图却有所不同,白色映射到白色。
这是原始帧缓冲区, the 智能转换通过 ddms,以及愚蠢的转换通过上述算法。请注意,后者稍微更暗、更绿。
(顺便说一句,这个转换是在ffmpeg中实现的,但它只是执行上面列出的愚蠢转换,使 LSB 全部为零。)
我想我有两个问题:
- 将 rgb565 转换为 rgb888 最明智的方法是什么?
- DDMS 如何转换其屏幕截图?
我的几分钱:
如果您关心精确映射和快速算法,您可以考虑这个:
R8 = ( R5 * 527 + 23 ) >> 6;
G8 = ( G6 * 259 + 33 ) >> 6;
B8 = ( B5 * 527 + 23 ) >> 6;
它只使用:MUL、ADD 和 SHR -> 所以速度相当快!
从另一面来看,它与具有适当舍入的浮点映射 100% 兼容:
// 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);
一些额外的美分:
如果您对 888 到 565 的转换感兴趣,这也非常有效:
R5 = ( R8 * 249 + 1014 ) >> 11;
G6 = ( G8 * 253 + 505 ) >> 10;
B5 = ( B8 * 249 + 1014 ) >> 11;
使用暴力搜索找到了常量,并进行了一些早期拒绝,以加快速度。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)