首先对不起,如果这是重复的,我找不到任何主题回答我的问题。
我正在编写一个小程序,用于将32位浮点值转换为short int(16位)和unsigned char(8位)值。这是用于HDR图像的目的。
来自here 我可以得到以下功能(没有夹紧):
static inline uint8_t u8fromfloat(float x)
{
return (int)(x * 255.0f);
}
我认为,通过乘以(pow( 2,16 ) -1)
然后我最终想到了有序的抖动,尤其是拜耳的抖动。 要转换为uint8_t,我想我可以使用4x4矩阵和8 * 8矩阵进行无符号短路。
我还想到了一个查找表来加速这个过程,这样:
uint16_t LUT[0x10000] // 2^16 values contained
并存储2 ^ 16个与浮点相对应的无符号短值。 同样的表也可以用于uint8_t,因为它之间存在隐式转换 unsigned short< - > unsigned int
但是这样的查找表不会在内存中占据巨大的位置吗?如何填写这样的表格?!
现在我很困惑,你最好的是什么? 谢谢你的帮助!
在顺风回答之后编辑:现在让我说我也想同时进行基本的颜色空间转换,即在转换为U8 / U16之前,进行颜色空间转换(浮动),然后将其缩小为U8 / U16。在这种情况下,不会使用更高效的lut吗?是的,我仍然有问题索引lut ..
答案 0 :(得分:1)
我看到它的方式,查找表无济于事,因为为了索引它,你需要将float转换为某种整数类型。赶上22。
该表需要0x10000 * sizeof(uint16_t)字节,即128 KB。现代标准不是很多,但另一方面缓存是宝贵的。但是,正如我所说的那样,该表并没有给解决方案增加太多,因为你需要将float转换为整数才能进行索引。
你可以将一个由浮点的原始位索引的表重新解释为整数,但这必须是32位,这将变得非常大(大约8 GB)。
进行您概述的直接运行时转换。
答案 1 :(得分:0)
坚持乘法 - 它会正常工作。
实际上,所有现代CPU都有适应这些内容的向量指令(SSE,AVX,...),因此您可能会考虑编程。或者使用自动矢量化代码的编译器(如果可能)(Intel C,也是GCC)。即使在表查找是一种可能的解决方案的情况下,这通常也会更快,因为您不会受到内存延迟的影响。
答案 2 :(得分:-1)
首先,应该注意float
具有24位精度,这不能适合16位int
甚至8位。其次,float的范围要大得多,不能存储在任何int
或long long int
所以你的问题标题实际上是不正确的,无法将任何浮动精确地转换为short或char。您希望 映射 0到1之间的浮点值到8位或16位int 范围。
对于您上面使用的代码,它会正常工作。但是值255极不可能返回因为它需要正好1.0作为输入,否则254.99999之类的值最终会被截断为254.你应该舍入值代替
return (int)(x * 255.0f + .5f);
或更好,请使用链接中提供的代码获取更多均衡分布
static inline uint8_t u8fromfloat_trick(float x)
{
union { float f; uint32_t i; } u;
u.f = 32768.0f + x * (255.0f / 256.0f);
return (uint8_t)u.i;
}
使用LUT不会更快,因为 16位值的表太大而无法适应缓存,实际上可能会大大降低您的性能。上面的代码段只需要2个浮点指令,或只需要1个FMA。 SIMD将进一步提高4-32倍(或更高)的性能,因此LUT方法很容易超越,因为并行化表格查找起来要困难得多