我已经制作了一个分色图像的功能。
// =(
#define ARGB_COLOR(a, r, g, b) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
inline UINT PosterizeColor(const UINT &color, const float &nColors)
{
__m128 clr = _mm_cvtepi32_ps( _mm_cvtepu8_epi32((__m128i&)color) );
clr = _mm_mul_ps(clr, _mm_set_ps1(nColors / 255.0f) );
clr = _mm_round_ps(clr, _MM_FROUND_TO_NEAREST_INT);
clr = _mm_mul_ps(clr, _mm_set_ps1(255.0f / nColors) );
__m128i iClr = _mm_cvttps_epi32(clr);
return ARGB_COLOR(iClr.m128i_u8[12],
iClr.m128i_u8[8],
iClr.m128i_u8[4],
iClr.m128i_u8[0]);
}
在第一行,我将颜色解压缩成4个浮点数,但我找不到正确的反向方法。
我搜索了SSE文档,找不到_mm_cvtepu8_epi32
是否存在?
答案 0 :(得分:8)
您需要_mm_shuffle_epi8
和_mm_cvtsi128_si32
的组合:
static const __m128i shuffleMask = _mm_setr_epi8(0, 4, 8, 12, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1);
UINT color = _mm_cvtsi128_si32(_mm_shuffle_epi8(iClr, shuffleMask));
答案 1 :(得分:5)
不幸的是,即使在AVX中也没有指令可以做到这一点(我不知道)。所以你必须像现在一样手动完成。
但是,您当前的方法非常不理想,并且您依赖.m128i_u8
这是MSVC扩展。根据我对MSVC的经验,它将使用对齐的缓冲区来访问各个元素。由于部分词语访问,这会受到非常严重的惩罚。
使用_mm_extract_epi32()
而不是.m128i_u8
。这是在SSE4.1中。但是你已经依赖SSE4.1和_mm_cvtepu8_epi32()
。
由于您使用的是1字节粒度,因此这种情况特别糟糕。如果您使用的是2字节(16位整数)粒度,则可以使用shuffle intrinsics提供有效的解决方案。