From 03c150d0a65c134dc6a9ee998565a768b5b233fc Mon Sep 17 00:00:00 2001 From: Alexander Date: Mon, 23 Jan 2017 16:25:05 +0300 Subject: [PATCH] SIMD Convert. sse4 version (still 1.4x faster than previous avx2 implementation) --- src/libImaging/Convert.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/libImaging/Convert.c b/src/libImaging/Convert.c index 7afacac2f..d6c1ca81a 100644 --- a/src/libImaging/Convert.c +++ b/src/libImaging/Convert.c @@ -593,6 +593,44 @@ rgba2rgbA(UINT8* out, const UINT8* in, int xsize) #endif + for (; x < xsize - 3; x += 4) { + __m128 mmaf; + __m128i pix0, pix1, pix2, pix3, mma; + __m128 mma0, mma1, mma2, mma3; + __m128 half = _mm_set1_ps(0.5); + __m128i source = _mm_loadu_si128((__m128i *) &in[x * 4]); + + mma = _mm_and_si128(source, _mm_set_epi8( + 0xff,0,0,0, 0xff,0,0,0, 0xff,0,0,0, 0xff,0,0,0)); + + mmaf = _mm_cvtepi32_ps(_mm_srli_epi32(source, 24)); + mmaf = _mm_mul_ps(_mm_set1_ps(255), _mm_rcp_ps(mmaf)); + + mma0 = _mm_shuffle_ps(mmaf, mmaf, 0x00); + mma1 = _mm_shuffle_ps(mmaf, mmaf, 0x55); + mma2 = _mm_shuffle_ps(mmaf, mmaf, 0xaa); + mma3 = _mm_shuffle_ps(mmaf, mmaf, 0xff); + + pix1 = _mm_unpacklo_epi8(source, _mm_setzero_si128()); + pix3 = _mm_unpackhi_epi8(source, _mm_setzero_si128()); + pix0 = _mm_unpacklo_epi16(pix1, _mm_setzero_si128()); + pix1 = _mm_unpackhi_epi16(pix1, _mm_setzero_si128()); + pix2 = _mm_unpacklo_epi16(pix3, _mm_setzero_si128()); + pix3 = _mm_unpackhi_epi16(pix3, _mm_setzero_si128()); + + pix0 = _mm_cvtps_epi32(_mm_add_ps(_mm_mul_ps(_mm_cvtepi32_ps(pix0), mma0), half)); + pix1 = _mm_cvtps_epi32(_mm_add_ps(_mm_mul_ps(_mm_cvtepi32_ps(pix1), mma1), half)); + pix2 = _mm_cvtps_epi32(_mm_add_ps(_mm_mul_ps(_mm_cvtepi32_ps(pix2), mma2), half)); + pix3 = _mm_cvtps_epi32(_mm_add_ps(_mm_mul_ps(_mm_cvtepi32_ps(pix3), mma3), half)); + + pix0 = _mm_packus_epi32(pix0, pix1); + pix2 = _mm_packus_epi32(pix2, pix3); + source = _mm_packus_epi16(pix0, pix2); + source = _mm_blendv_epi8(source, mma, _mm_set_epi8( + 0xff,0,0,0, 0xff,0,0,0, 0xff,0,0,0, 0xff,0,0,0)); + _mm_storeu_si128((__m128i *) &out[x * 4], source); + } + in = &in[x * 4]; out = &out[x * 4];