Global threshold writing into caller-supplied buffer.
119{
120 const size_t n =
static_cast<size_t>(w) *
h;
121
122 std::for_each(std::execution::par_unseq,
123 std::views::iota(uint32_t { 0 },
h).begin(),
124 std::views::iota(uint32_t { 0 },
h).end(),
125 [&](uint32_t row) {
126 const float* src_row = gray.data() + static_cast<size_t>(row) * w;
127 float* dst_row =
dst.data() +
static_cast<size_t>(row) * w * 4;
128
129#ifdef MAYAFLUX_ARCH_X64
130
131
132 const __m256 alpha_mask = _mm256_set_ps(1.0F, 0.0F, 0.0F, 0.0F,
133 1.0F, 0.0F, 0.0F, 0.0F);
135 for (;
px + 2 <= w;
px += 2) {
136 const float g0 = src_row[
px];
137 const float g1 = src_row[
px + 1];
138
139 __m256 v = _mm256_set_ps(1.0F, g1, g1, g1, 1.0F, g0, g0, g0);
140 _mm256_storeu_ps(dst_row +
px * 4, v);
141 }
142 for (;
px < w; ++
px) {
143 const float v = src_row[
px];
144 dst_row[
px * 4] = dst_row[
px * 4 + 1] = dst_row[
px * 4 + 2] = v;
145 dst_row[
px * 4 + 3] = 1.0F;
146 }
147
148#elif defined(MAYAFLUX_ARCH_ARM64)
149 const float32x4_t
alpha = vdupq_n_f32(1.0F);
151 for (;
px + 4 <= w;
px += 4) {
152 float32x4_t g = vld1q_f32(src_row +
px);
153 float32x4_t lo = vzip1q_f32(g, g);
154 float32x4_t hi = vzip2q_f32(g, g);
155 float32x4x2_t p01 = vzipq_f32(lo, vdupq_lane_f32(vget_low_f32(
alpha), 0));
156
157 float32x4x4_t rgba;
158 rgba.val[0] = g;
159 rgba.val[1] = g;
160 rgba.val[2] = g;
162 vst4q_f32(dst_row +
px * 4, rgba);
163 (void)lo;
164 (void)hi;
165 (void)p01;
166 }
167 for (;
px < w; ++
px) {
168 const float v = src_row[
px];
170 dst_row[
px * 4 + 1] = v;
171 dst_row[
px * 4 + 2] = v;
172 dst_row[
px * 4 + 3] = 1.0F;
173 }
174
175#else
176 for (uint32_t
px = 0;
px < w; ++
px) {
177 const float v = src_row[
px];
179 dst_row[
px * 4 + 1] = v;
180 dst_row[
px * 4 + 2] = v;
181 dst_row[
px * 4 + 3] = 1.0F;
182 }
183#endif
184 });
185}