2013-01-08 127 views
0

首先抱歉,如果这是重复的,我找不到任何主题回答我的问题。将float 32精确地转换为unsigned short或unsigned char

我正在编写一个小程序,将用于将32位浮点值转换为短整型(16位)和无符号字符(8位)值。这是用于HDR图像的目的。

here 我能得到下面的函数(无钳位):

static inline uint8_t u8fromfloat(float x) 
{ 
    return (int)(x * 255.0f); 
} 

我想,以同样的方式,我们可以通过(pow(2,16) -1)

相乘得到短整型但后来我结束了思考有序抖动,特别是拜耳抖动。 要转换为uint8_t我想我可以使用4x4矩阵和8 * 8矩阵作为unsigned short。

我还想到了查找表的来加速的过程中,这种方式:相应于浮子

uint16_t LUT[0x10000] // 2^16 values contained 

和存储2^16无符号短值。 这同一个表可以再用于uint8_t以及因为隐式转换之间 无符号短< - > unsigned int类型

但不会像这样的查询表在内存巨大?还有人会如何填满这样的桌子?!

现在我很困惑,根据你最好什么? 感谢您的帮助!

uwind后编辑回答:现在我想说,我也想同时进行基本色彩空间转换,即在转换为U8/U16之前,做一个色彩空间转换(以浮点形式),然后缩小它到U8/U16。在这种情况下不会使用lut更高效?是的,我仍然有问题,以指数卢特..

+0

我认为这是一个C问题。 – Jodrell

+0

是的,我忘了确切地说,它是C/C++ – Lex

回答

1

我看到它的方式,查找表将无济于事,因为为了索引它,您需要将float转换为某种整数类型。捕获22.

该表需要0x10000 * sizeof(uint16_t)个字节,即128 KB。现代标准并不是很多,但另一方面缓存是宝贵的。但是,正如我所说,该表并没有增加很多解决方案,因为您需要将float转换为整数才能进行索引。

你可以做一个表,它被重新解释为整数的浮点的原始位索引,但是这必须是32位,它变得非常大(8GB左右)。

请转到您列出的直接运行时转换。

+0

感谢您的意见。现在假设我也想同时进行基本色彩空间转换,即在转换为U8/U16之前,进行色彩空间转换(以浮点形式),然后将其缩小为U8/U16。在这种情况下不会使用lut更高效?是的,我仍然有问题来索引lut ... – Lex

0

只要保持乘法 - 它会正常工作。

几乎所有的现代CPU都有适合这个东西的矢量指令(SSE,AVX ......),所以你可以看看编程。如果可能的话,还可以使用自动向量化代码的编译器(英特尔C和GCC)。即使在查表是一种可能的解决方案的情况下,这通常会更快,因为您不会遭受内存延迟。

-1

首先,float具有24位的精度,它不能适合16位int或甚至8位。其次,float有更大的范围,不能存储在任何int或long long int

所以你的问题是不正确的,没有办法精确地将任何float转换为short或char。它可以更准确地表达为将32位浮点像素值转换为8位或16位。

为你使用上面的代码中,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个浮点指令,或者只用FMA指令就足够了。 SIMD将进一步提高性能4-8倍,所以LUT方法将很容易胜过,因为你无法并行化表查找

相关问题