MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches

◆ downsample_2x() [1/3]

MAYAFLUX_API void MayaFlux::Kinesis::Vision::downsample_2x ( std::span< const float >  src,
std::span< float >  dst,
uint32_t  w,
uint32_t  h,
uint32_t &  new_w,
uint32_t &  new_h 
)

2x box-filter downsample writing into a caller-supplied buffer.

Parameters
srcInput span, size w * h.
dstOutput span, size must be >= floor(w/2) * floor(h/2).
wInput width in pixels.
hInput height in pixels.
new_wReceives output width.
new_hReceives output height.

Definition at line 423 of file PixelOps.cpp.

428{
429 new_w = w / 2;
430 new_h = h / 2;
431
432 std::for_each(std::execution::par_unseq,
433 std::views::iota(uint32_t { 0 }, new_h).begin(),
434 std::views::iota(uint32_t { 0 }, new_h).end(),
435 [&](uint32_t oy) {
436 const float* row0 = src.data() + static_cast<size_t>(oy * 2) * w;
437 const float* row1 = src.data() + static_cast<size_t>(oy * 2 + 1) * w;
438 float* drow = dst.data() + static_cast<size_t>(oy) * new_w;
439
440#ifdef MAYAFLUX_ARCH_X64
441 const __m256 quarter = _mm256_set1_ps(0.25F);
442 uint32_t ox = 0;
443 for (; ox + 8 <= new_w; ox += 8) {
444
445 __m256 r0a = _mm256_loadu_ps(row0 + ox * 2); // px 0..7 of row0
446 __m256 r0b = _mm256_loadu_ps(row0 + ox * 2 + 8); // px 8..15 of row0
447 __m256 r1a = _mm256_loadu_ps(row1 + ox * 2);
448 __m256 r1b = _mm256_loadu_ps(row1 + ox * 2 + 8);
449
450 // horizontal add pairs: hadd gains (a0+a1, a2+a3, b0+b1, b2+b3 | ...)
451 __m256 sum0 = _mm256_hadd_ps(r0a, r0b); // (r00+r01, r02+r03, r08+r09, r010+r011 | ...)
452 __m256 sum1 = _mm256_hadd_ps(r1a, r1b);
453 __m256 sum = _mm256_add_ps(sum0, sum1);
454
455 __m256d perm_d = _mm256_permute4x64_pd(_mm256_castps_pd(sum), _MM_SHUFFLE(3, 1, 2, 0));
456 __m256 result = _mm256_mul_ps(_mm256_castpd_ps(perm_d), quarter);
457 _mm256_storeu_ps(drow + ox, result);
458 }
459 for (; ox < new_w; ++ox) {
460 drow[ox] = (row0[ox * 2] + row0[ox * 2 + 1]
461 + row1[ox * 2] + row1[ox * 2 + 1])
462 * 0.25F;
463 }
464
465#elif defined(MAYAFLUX_ARCH_ARM64)
466 const float32x4_t quarter = vdupq_n_f32(0.25F);
467 uint32_t ox = 0;
468 for (; ox + 4 <= new_w; ox += 4) {
469 // vld2q_f32 loads 8 floats deinterleaved into 2 registers:
470 // val[0] = even elements, val[1] = odd elements
471 float32x4x2_t r0 = vld2q_f32(row0 + ox * 2);
472 float32x4x2_t r1 = vld2q_f32(row1 + ox * 2);
473 // r0.val[0] = [row0[0], row0[2], row0[4], row0[6]]
474 // r0.val[1] = [row0[1], row0[3], row0[5], row0[7]]
475 float32x4_t sum = vaddq_f32(
476 vaddq_f32(r0.val[0], r0.val[1]),
477 vaddq_f32(r1.val[0], r1.val[1]));
478 vst1q_f32(drow + ox, vmulq_f32(sum, quarter));
479 }
480 for (; ox < new_w; ++ox) {
481 drow[ox] = (row0[ox * 2] + row0[ox * 2 + 1]
482 + row1[ox * 2] + row1[ox * 2 + 1])
483 * 0.25F;
484 }
485
486#else
487 for (uint32_t ox = 0; ox < new_w; ++ox) {
488 drow[ox] = (row0[ox * 2] + row0[ox * 2 + 1]
489 + row1[ox * 2] + row1[ox * 2 + 1])
490 * 0.25F;
491 }
492#endif
493 });
494}
uint32_t h
Definition InkPress.cpp:29
uint32_t * dst
const uint32_t * src
std::vector< double > sum(std::span< const double > data, size_t n_windows, uint32_t hop_size, uint32_t window_size)
Sum per window.
Definition Analysis.cpp:469

References dst, h, and src.

Referenced by downsample_2x(), downsample_2x(), and MayaFlux::Kinesis::Vision::VisionExecutor::run().

+ Here is the caller graph for this function: