2011-12-22 26 views
4

イメージをポスタリゼーションする機能を作っています。最初の行に_m128iをSSEの符号なし整数に変換するにはどうすればよいですか?

// =(
#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のドキュメントを通して検索し、1が存在しない_mm_cvtepu8_epi32

の逆を見つけることができませんでしたか?

答えて

5

残念ながら、AVX(これは私が知っていることはありません)でもそれを行うための指示はありません。今のように手作業で行う必要があります。

しかし、現在の方法は非常に最適ではなく、.m128i_u8(MSVC拡張機能)に依存しています。 MSVCに関する私の経験に基づいて、個々の要素にアクセスするために調整されたバッファを使用します。部分的な単語アクセスのため、これには非常に重いペナルティがあります。

.m128i_u8の代わりに_mm_extract_epi32()を使用してください。これはSSE4.1にあります。しかし、すでに_mm_cvtepu8_epi32()でSSE4.1に頼っています。

この状況は、1バイト単位で作業しているため、特に悪いことです。代わりに2バイト(16ビット整数)の粒度で作業していた場合、shuffle intrinsicsを使用する効率的なソリューションがあります。

+0

_mm_extract_epi32は()ビットを助けたが、あなたは「非常に次善」とはどういう意味ですか? – bitwise

+0

一般的に言えば、データを保存してすぐに別の単語サイズで再度アクセスしようとすると、大きなペナルティが発生します。私が見てきたことから、MSVCの 'xmm'レジスタの要素を抽出する方法は、これを正確に行うことです。すなわち、メモリに格納し、別々にアクセスします。しかし、この特定のケースは最悪のシナリオではないと思います。 – Mysticial

+0

とにかく、2048x2048の22msで動作するようになりました。これは今のところ十分です。ありがとう=) – bitwise

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)); 
+0

小さな間違い: '_mm_set_epi8'は' _mm_setr_epi8'です。それ以外の場合、これは実際に動作します!私は驚き、+1。私はSSSE3がバイト単位のシャッフルを持っていたことに気づいていませんでした。 – Mysticial

+0

これに感謝しますが、私もこれを行うことができ、上記の結果とほぼ同じ結果になりました。 \t \t iClr = _mm_packs_epi32(iClr、_mm_setzero_si128()); \t \t iClr = _mm_packus_epi16(iClr、_mm_setzero_si128()); \t \t UINT color =(UINT)_mm_extract_epi32(iClr、0); - 整数計算を使用してルーチンを書き直した後、asmに変換して、2048x2048の画像で8〜9msという最高の結果を得ました。 – bitwise

+0

@bitwise私はこれが受け入れられた答えであるべきだと思います。 – Antonio

関連する問題