Convert RGBA to luminance gray using BT.601 coefficients.
Output is one float per pixel. Alpha channel is discarded. Coefficients: R*0.299 + G*0.587 + B*0.114
19{
20 const size_t n =
static_cast<size_t>(w) *
h;
21
22 P::for_each(P::par_unseq,
23 std::views::iota(uint32_t { 0 },
h).begin(),
24 std::views::iota(uint32_t { 0 },
h).end(),
25 [&](uint32_t row) {
26 const float* src_row = rgba.data() + static_cast<size_t>(row) * w * 4;
27 float* dst_row = dst.data() + static_cast<size_t>(row) * w;
28
29#ifdef MAYAFLUX_ARCH_X64
30 uint32_t px = 0;
31 for (; px + 8 <= w; px += 8) {
32 __m128 a0 = _mm_loadu_ps(src_row + px * 4);
33 __m128 a1 = _mm_loadu_ps(src_row + px * 4 + 4);
34 __m128 a2 = _mm_loadu_ps(src_row + px * 4 + 8);
35 __m128 a3 = _mm_loadu_ps(src_row + px * 4 + 12);
36 _MM_TRANSPOSE4_PS(a0, a1, a2, a3);
37 __m128
lo = _mm_fmadd_ps(a0, _mm_set1_ps(0.299F),
38 _mm_fmadd_ps(a1, _mm_set1_ps(0.587F),
39 _mm_mul_ps(a2, _mm_set1_ps(0.114F))));
40
41 __m128 b0 = _mm_loadu_ps(src_row + px * 4 + 16);
42 __m128 b1 = _mm_loadu_ps(src_row + px * 4 + 20);
43 __m128 b2 = _mm_loadu_ps(src_row + px * 4 + 24);
44 __m128 b3 = _mm_loadu_ps(src_row + px * 4 + 28);
45 _MM_TRANSPOSE4_PS(b0, b1, b2, b3);
46 __m128
hi = _mm_fmadd_ps(b0, _mm_set1_ps(0.299F),
47 _mm_fmadd_ps(b1, _mm_set1_ps(0.587F),
48 _mm_mul_ps(b2, _mm_set1_ps(0.114F))));
49
50 _mm256_storeu_ps(dst_row + px, _mm256_set_m128(
hi,
lo));
51 }
52 for (; px < w; ++px) {
53 const size_t p = px * 4;
54 dst_row[px] = src_row[p] * 0.299F
55 + src_row[p + 1] * 0.587F
56 + src_row[p + 2] * 0.114F;
57 }
58
59#elif defined(MAYAFLUX_ARCH_ARM64)
60 const float32x4_t k_r = vdupq_n_f32(0.299F);
61 const float32x4_t k_g = vdupq_n_f32(0.587F);
62 const float32x4_t k_b = vdupq_n_f32(0.114F);
63 uint32_t px = 0;
64 for (; px + 4 <= w; px += 4) {
65 float32x4x4_t p = vld4q_f32(src_row + px * 4);
66 vst1q_f32(dst_row + px,
67 vmlaq_f32(vmlaq_f32(vmulq_f32(p.val[0], k_r), p.val[1], k_g), p.val[2], k_b));
68 }
69 for (; px < w; ++px) {
70 const size_t p = px * 4;
71 dst_row[px] = src_row[p] * 0.299F
72 + src_row[p + 1] * 0.587F
73 + src_row[p + 2] * 0.114F;
74 }
75
76#else
77 for (uint32_t px = 0; px < w; ++px) {
78 const size_t p = px * 4;
79 dst_row[px] = src_row[p] * 0.299F
80 + src_row[p + 1] * 0.587F
81 + src_row[p + 2] * 0.114F;
82 }
83#endif
84 });
85}