title: De-interleave image channel in SSE 16 bit vectors
body: <p>byte I have 32 bpp image. I need to de interleave R G B color channels in diferent 16 bits vectors i am using following code to do that( <a href="https://stackoverflow.com/questions/35871639/how-to-deinterleave-image-channel-in-sse">how to deinterleave image channel in SSE</a>)</p>
  
  <pre><code>  // deinterleave chaneel R, G, B ,A in 16 bits vectors
    {
       __m128i vrgba = _mm_loadu_si128((__m128i *)(pSrc));
       __m128i vr1 = _mm_and_si128(vrgba, _mm_set1_epi32(0xff));
       __m128i vg1 = _mm_and_si128(_mm_srli_epi32(vrgba, 8), _mm_set1_epi32(0xff));
       __m128i vb1 = _mm_and_si128(_mm_srli_epi32(vrgba, 16), _mm_set1_epi32(0xff));
       __m128i va1 = _mm_srli_epi32(vrgba, 24);
  
       vrgba = _mm_loadu_si128((__m128i *)(pSrc + 4));  // since pSrc is uint32_t type
       __m128i vr2 = _mm_and_si128(vrgba, _mm_set1_epi32(0xff));
       __m128i vg2 = _mm_and_si128(_mm_srli_epi32(vrgba, 8), _mm_set1_epi32(0xff));
       __m128i vb2 = _mm_and_si128(_mm_srli_epi32(vrgba, 16), _mm_set1_epi32(0xff));
       __m128i va2 = _mm_srli_epi32(vrgba, 24);
  
       vr = _mm_packs_epi32(vr1, vr2);
       vg = _mm_packs_epi32(vg1, vg2);
       vb = _mm_packs_epi32(vb1, vb2);
       va = _mm_packs_epi32(va1, va2);
    }
  </code></pre>
  
  <p>can we make this more efficient? Below is the code for Gaussian with out de-interleaving channels.I am finding it terribly inefficient</p>
  
  <pre><code>    static inline void ConvertTo16Bits(__m128i&amp; v1, __m128i&amp; v2, const __m128i&amp; v0)
      {
          __m128i const zero = _mm_setzero_si128();
          v1 = _mm_unpacklo_epi8(v0, zero);
          v2 = _mm_unpackhi_epi8(v0, zero);
      }
  
      static inline void mul32bits(__m128i &amp;vh, __m128i &amp;vl,           // output - 2x4xint32_t
          const __m128i&amp; v0, const __m128i&amp; v1) // input  - 2x8xint16_t
      {
          const __m128i vhi = _mm_mulhi_epu16(v0, v1);
          const __m128i vlo = _mm_mullo_epi16(v0, v1);
          vh = _mm_unpacklo_epi16(vlo, vhi);
          vl = _mm_unpackhi_epi16(vlo, vhi);
      }
  
      struct Pixel
      {
          unsigned char r;
          unsigned char g;
          unsigned char b;
          unsigned char a;
      };
  
      void computePixelvalue(unsigned int * pixelArray, int count, unsigned short * gaussArray, Pixel&amp; out)
      {
          __m128i sumRGBA;
          sumRGBA = _mm_set1_epi32(0);
          unsigned int countMod4 = count % 4;
          unsigned int b, g, r, a;
          constexpr int shuffle = _MM_SHUFFLE(3, 1, 0, 0);
  
          while (count &gt;= 4)
          {
              __m128i vrgba = _mm_loadu_si128((__m128i *)(pixelArray));
              __m128i rgba12, rgba34;
  
              ConvertTo16Bits(rgba12, rgba34, vrgba);
  
              unsigned short s1 = *gaussArray++;
              unsigned short s2 = *gaussArray++;
  
              __m128i shift8 = _mm_set1_epi16(s1);
              __m128i shift16 = _mm_set1_epi16(s2);
              __m128i gaussVector = _mm_shuffle_epi32(_mm_unpacklo_epi32(shift8, shift16), shuffle);
  
              __m128i multl, multh;
              mul32bits(multl, multh, rgba12, gaussVector);
              sumRGBA = _mm_add_epi32(sumRGBA, multl);
              sumRGBA = _mm_add_epi32(sumRGBA, multh);
  
              s1 = *gaussArray++;
              s2 = *gaussArray++;
              shift8 = _mm_set1_epi16(s1);
              shift16 = _mm_set1_epi16(s2);
              gaussVector = _mm_shuffle_epi32(_mm_unpacklo_epi32(shift8, shift16), shuffle);
  
              mul32bits(multl, multh, rgba34, gaussVector);
              sumRGBA = _mm_add_epi32(sumRGBA, multl);
              sumRGBA = _mm_add_epi32(sumRGBA, multh);
  
              count = count - 4;
              pixelArray = pixelArray + 4;
          }
  
          r = sumRGBA.m128i_u32[0];
          g = sumRGBA.m128i_u32[1];
          b = sumRGBA.m128i_u32[2];
          a = sumRGBA.m128i_u32[3];
  
          while (countMod4)
          {
              auto pixelArrayByte = reinterpret_cast&lt;unsigned char*&gt;(pixelArray);
  
              unsigned short k = static_cast&lt;unsigned short&gt;(*gaussArray++);
              r += *pixelArrayByte++ * k;
              g += *pixelArrayByte++ * k;
              b += *pixelArrayByte++ * k;
              a += *pixelArrayByte++ * k;
  
              countMod4--;
          }
  
          out.r = static_cast&lt;unsigned char&gt;(r &gt;&gt; 15);
          out.g = static_cast&lt;unsigned char&gt;(g &gt;&gt; 15);
          out.b = static_cast&lt;unsigned char&gt;(b &gt;&gt; 15);
          out.a = static_cast&lt;unsigned char&gt;(a &gt;&gt; 15);
      }
  </code></pre>