MayaFlux 0.5.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 443 of file PixelOps.cpp.

448{
449 new_w = w / 2;
450 new_h = h / 2;
451
452 P::for_each(P::par_unseq,
453 std::views::iota(uint32_t { 0 }, new_h).begin(),
454 std::views::iota(uint32_t { 0 }, new_h).end(),
455 [&](uint32_t oy) {
456 const float* row0 = src.data() + static_cast<size_t>(oy * 2) * w;
457 const float* row1 = src.data() + static_cast<size_t>(oy * 2 + 1) * w;
458 float* drow = dst.data() + static_cast<size_t>(oy) * new_w;
459
460#ifdef MAYAFLUX_ARCH_X64
461 const __m256 quarter = _mm256_set1_ps(0.25F);
462 uint32_t ox = 0;
463 for (; ox + 8 <= new_w; ox += 8) {
464
465 __m256 r0a = _mm256_loadu_ps(row0 + ox * 2); // px 0..7 of row0
466 __m256 r0b = _mm256_loadu_ps(row0 + ox * 2 + 8); // px 8..15 of row0
467 __m256 r1a = _mm256_loadu_ps(row1 + ox * 2);
468 __m256 r1b = _mm256_loadu_ps(row1 + ox * 2 + 8);
469
470 // horizontal add pairs: hadd gains (a0+a1, a2+a3, b0+b1, b2+b3 | ...)
471 __m256 sum0 = _mm256_hadd_ps(r0a, r0b); // (r00+r01, r02+r03, r08+r09, r010+r011 | ...)
472 __m256 sum1 = _mm256_hadd_ps(r1a, r1b);
473 __m256 sum = _mm256_add_ps(sum0, sum1);
474
475 __m256d perm_d = _mm256_permute4x64_pd(_mm256_castps_pd(sum), _MM_SHUFFLE(3, 1, 2, 0));
476 __m256 result = _mm256_mul_ps(_mm256_castpd_ps(perm_d), quarter);
477 _mm256_storeu_ps(drow + ox, result);
478 }
479 for (; ox < new_w; ++ox) {
480 drow[ox] = (row0[ox * 2] + row0[ox * 2 + 1]
481 + row1[ox * 2] + row1[ox * 2 + 1])
482 * 0.25F;
483 }
484
485#elif defined(MAYAFLUX_ARCH_ARM64)
486 const float32x4_t quarter = vdupq_n_f32(0.25F);
487 uint32_t ox = 0;
488 for (; ox + 4 <= new_w; ox += 4) {
489 // vld2q_f32 loads 8 floats deinterleaved into 2 registers:
490 // val[0] = even elements, val[1] = odd elements
491 float32x4x2_t r0 = vld2q_f32(row0 + ox * 2);
492 float32x4x2_t r1 = vld2q_f32(row1 + ox * 2);
493 // r0.val[0] = [row0[0], row0[2], row0[4], row0[6]]
494 // r0.val[1] = [row0[1], row0[3], row0[5], row0[7]]
495 float32x4_t sum = vaddq_f32(
496 vaddq_f32(r0.val[0], r0.val[1]),
497 vaddq_f32(r1.val[0], r1.val[1]));
498 vst1q_f32(drow + ox, vmulq_f32(sum, quarter));
499 }
500 for (; ox < new_w; ++ox) {
501 drow[ox] = (row0[ox * 2] + row0[ox * 2 + 1]
502 + row1[ox * 2] + row1[ox * 2 + 1])
503 * 0.25F;
504 }
505
506#else
507 for (uint32_t ox = 0; ox < new_w; ++ox) {
508 drow[ox] = (row0[ox * 2] + row0[ox * 2 + 1]
509 + row1[ox * 2] + row1[ox * 2 + 1])
510 * 0.25F;
511 }
512#endif
513 });
514}
uint32_t h
Definition InkPress.cpp:28
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 h.

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

+ Here is the caller graph for this function: