我怎么可以转换成一个字节的缓冲区(从0至255)浮动的缓冲区(从0.0至1.0)?当然应该有一个之间的关系的两个价值观,例如:0在字节的缓冲区将可以。0.f在浮动的缓冲器,128字节的缓冲区将可以。5f浮动的缓冲器,255字节的缓冲区将1.f在浮动的缓冲器。

实际上这是代码,我有:

for (int y=0;y<height;y++) {
    for (int x=0;x<width;x++) {
        float* floatpixel = floatbuffer + (y * width + x) * 4;
        BYTE* bytepixel = (bytebuffer + (y * width + x) * 4);
        floatpixel[0] = bytepixel[0]/255.f;
        floatpixel[1] = bytepixel[1]/255.f;
        floatpixel[2] = bytepixel[2]/255.f;
        floatpixel[3] = 1.0f; // A
    }
}

这个运行速度非常缓慢。我的一个朋友的建议我要用的转换表,但我想知道如果别人能给我另一种方法。

有帮助吗?

解决方案

无论您选择使用查找表或没有,你的代码是做了很多工作,每次循环迭代它真的并不需要 - 可能足以掩盖转换的成本和繁衍

声明你的指针限制,和指针你只能从常量读取。由1/255,而不是由255分别在内部循环的每次迭代计算所述指针相乘,只是计算的初始值和递增它们。展开内部循环几次。如果你的目标是支持使用矢量SIMD操作。不要递增,最大,减量化比较和零比较来代替。

的东西
float* restrict floatpixel = floatbuffer;
BYTE const* restrict bytepixel = bytebuffer;
for( int size = width*height; size > 0; --size )
{
    floatpixel[0] = bytepixel[0]*(1.f/255.f);
    floatpixel[1] = bytepixel[1]*(1.f/255.f);
    floatpixel[2] = bytepixel[2]*(1.f/255.f);
    floatpixel[3] = 1.0f; // A
    floatpixel += 4;
    bytepixel += 4;
}

将是一个开始。

其他提示

我知道这是一个老问题,但由于没有人给使用IEEE浮点表示一种解决方案,在这里是一个。

// Use three unions instead of one to avoid pipeline stalls
union { float f; uint32_t i; } t, u, v, w;
t.f = 32768.0f;
float const b = 256.f / 255.f;

for(int size = width * height; size > 0; --size)
{
    u.i = t.i | bytepixel[0]; floatpixel[0] = (u.f - t.f) * b;
    v.i = t.i | bytepixel[1]; floatpixel[1] = (v.f - t.f) * b;
    w.i = t.i | bytepixel[2]; floatpixel[2] = (w.f - t.f) * b;
    floatpixel[3] = 1.0f; // A
    floatpixel += 4;
    bytepixel += 4;
}

这是超过的快两倍作为intfloat我的计算机(Core 2 Duo处理器)上的转换。

下面是上面的代码,在一个时间确实16个漂浮的SSE3版本。它需要bytepixelfloatpixel被128位对齐,总大小是4注多了SSE3内置的int转换浮动不会太大帮助这里,因为他们将需要额外的乘法反正。我相信这是去指令明智的最短途径,但如果你的编译器是不够聪明的你不妨用手展开和安排的事情。

/* Magic values */
__m128i zero = _mm_set_epi32(0, 0, 0, 0);
__m128i magic1 = _mm_set_epi32(0xff000000, 0xff000000, 0xff000000, 0xff000000);
__m128i magic2 = _mm_set_epi32(0x47004700, 0x47004700, 0x47004700, 0x47004700);
__m128 magic3 = _mm_set_ps(32768.0f, 32768.0f, 32768.0f, 32768.0f);
__m128 magic4 = _mm_set_ps(256.0f / 255.0f, 256.0f / 255.0f, 256.0f / 255.0f, 256.0f / 255.0f);

for(int size = width * height / 4; size > 0; --size)
{
    /* Load bytes in vector and force alpha value to 255 so that
     * the output will be 1.0f as expected. */
    __m128i in = _mm_load_si128((__m128i *)bytepixel);
    in = _mm_or_si128(in, magic1);

    /* Shuffle bytes into four ints ORed with 32768.0f and cast
     * to float (the cast is free). */
    __m128i tmplo = _mm_unpacklo_epi8(in, zero);
    __m128i tmphi = _mm_unpackhi_epi8(in, zero);
    __m128 in1 = _mm_castsi128_ps(_mm_unpacklo_epi16(tmplo, magic2));
    __m128 in2 = _mm_castsi128_ps(_mm_unpackhi_epi16(tmplo, magic2));
    __m128 in3 = _mm_castsi128_ps(_mm_unpacklo_epi16(tmphi, magic2));
    __m128 in4 = _mm_castsi128_ps(_mm_unpackhi_epi16(tmphi, magic2));

    /* Subtract 32768.0f and multiply by 256.0f/255.0f */
    __m128 out1 = _mm_mul_ps(_mm_sub_ps(in1, magic3), magic4);
    __m128 out2 = _mm_mul_ps(_mm_sub_ps(in2, magic3), magic4);
    __m128 out3 = _mm_mul_ps(_mm_sub_ps(in3, magic3), magic4);
    __m128 out4 = _mm_mul_ps(_mm_sub_ps(in4, magic3), magic4);

    /* Store 16 floats */
    _mm_store_ps(floatpixel, out1);
    _mm_store_ps(floatpixel + 4, out2);
    _mm_store_ps(floatpixel + 8, out3);
    _mm_store_ps(floatpixel + 12, out4);

    floatpixel += 16;
    bytepixel += 16;
}

修改:通过使用代替(f + c/b) * b f * b + c提高准确度

修改:添加SSE3版本

使用一个静态查找表此。当我在计算机图形公司工作,我们最后不得不为此,我们与项目挂钩的硬编码查找表。

你需要找出什么样的瓶颈是:

  • 如果你迭代数据表中的"错误"的方向,你不断地打了一个高速缓冲错过。没有查询将不断帮助。
  • 如果你的处理器速度较慢,在扩大于在看起来,你可以提高性能的看起来,提供查阅表适合它的高速缓存。

另一个提示:

struct Scale {
    BYTE operator()( const float f ) const { return f * 1./255; }
};
std::transform( float_table, float_table + itssize, floatpixel, Scale() );

是,查找表肯定比在一个循环中做了很多部门的更快。刚生成256个预先计算的浮点值的表,并使用字节值来索引该表。

您还可以通过删除索引计算优化环路一点点,只是做一些像

float *floatpixel = floatbuffer;
BYTE *bytepixel = bytebuffer;

for (...) {
  *floatpixel++ = float_table[*bytepixel++];
  *floatpixel++ = float_table[*bytepixel++];
  *floatpixel++ = float_table[*bytepixel++];
  *floatpixel++ = 1.0f;
}

查找表转换的最快方式:)在这里你去:

Python代码来生成byte_to_float.h文件以包括:

#!/usr/bin/env python

def main():
    print "static const float byte_to_float[] = {"

    for ii in range(0, 255):
        print "%sf," % (ii/255.0)

    print "1.0f };"    
    return 0

if __name__ == "__main__":
    main()

和C ++代码,以获得转换:

floatpixel[0] = byte_to_float[ bytepixel[0] ];

简单,不是吗?

不计算每次1/255。不知道是不是一个编译器会聪明地删除此。计算一次,每次都重新涂抹。更好的是,将其定义为一个常数。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top