Global threshold writing into caller-supplied buffer.
139{
140 const size_t n =
static_cast<size_t>(w) *
h;
141
142 P::for_each(P::par_unseq,
143 std::views::iota(uint32_t { 0 },
h).begin(),
144 std::views::iota(uint32_t { 0 },
h).end(),
145 [&](uint32_t row) {
146 const float* src_row = gray.data() + static_cast<size_t>(row) * w;
147 float* dst_row = dst.data() + static_cast<size_t>(row) * w * 4;
148
149#ifdef MAYAFLUX_ARCH_X64
150
151
152 const __m256 alpha_mask = _mm256_set_ps(1.0F, 0.0F, 0.0F, 0.0F,
153 1.0F, 0.0F, 0.0F, 0.0F);
154 uint32_t px = 0;
155 for (; px + 2 <= w; px += 2) {
156 const float g0 = src_row[px];
157 const float g1 = src_row[px + 1];
158
159 __m256 v = _mm256_set_ps(1.0F, g1, g1, g1, 1.0F, g0, g0, g0);
160 _mm256_storeu_ps(dst_row + px * 4, v);
161 }
162 for (; px < w; ++px) {
163 const float v = src_row[px];
164 dst_row[px * 4] = dst_row[px * 4 + 1] = dst_row[px * 4 + 2] = v;
165 dst_row[px * 4 + 3] = 1.0F;
166 }
167
168#elif defined(MAYAFLUX_ARCH_ARM64)
169 const float32x4_t alpha = vdupq_n_f32(1.0F);
170 uint32_t px = 0;
171 for (; px + 4 <= w; px += 4) {
172 float32x4_t g = vld1q_f32(src_row + px);
173 float32x4_t
lo = vzip1q_f32(g, g);
174 float32x4_t
hi = vzip2q_f32(g, g);
175 float32x4x2_t p01 = vzipq_f32(
lo, vdupq_lane_f32(vget_low_f32(alpha), 0));
176
177 float32x4x4_t rgba;
178 rgba.val[0] = g;
179 rgba.val[1] = g;
180 rgba.val[2] = g;
181 rgba.val[3] = alpha;
182 vst4q_f32(dst_row + px * 4, rgba);
185 (void)p01;
186 }
187 for (; px < w; ++px) {
188 const float v = src_row[px];
189 dst_row[px * 4] = v;
190 dst_row[px * 4 + 1] = v;
191 dst_row[px * 4 + 2] = v;
192 dst_row[px * 4 + 3] = 1.0F;
193 }
194
195#else
196 for (uint32_t px = 0; px < w; ++px) {
197 const float v = src_row[px];
198 dst_row[px * 4] = v;
199 dst_row[px * 4 + 1] = v;
200 dst_row[px * 4 + 2] = v;
201 dst_row[px * 4 + 3] = 1.0F;
202 }
203#endif
204 });
205}