MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Pyramid.hpp
Go to the documentation of this file.
1#pragma once
2
3/**
4 * @file Pyramid.hpp
5 * @brief Placement of an image pyramid inside a single atlas.
6 *
7 * Pure geometry. No MayaFlux type dependencies and no notion of what the
8 * texels hold, so the same layout serves a CPU pyramid, a GPU atlas image, or
9 * a test that checks where a level landed.
10 */
11
13
14/**
15 * @brief Extent and position of one pyramid level inside an atlas.
16 */
18 uint32_t ox { 0 };
19 uint32_t oy { 0 };
20 uint32_t w { 0 };
21 uint32_t h { 0 };
22};
23
24/**
25 * @brief Placement of every pyramid level in a single atlas.
26 *
27 * Level 0 occupies the left block at full size. Deeper levels are stacked in a
28 * column to its right, each half the size of the one before (rounded up), so
29 * the whole pyramid is one image.
30 */
32 static constexpr uint32_t k_max_levels = 6;
33
34 std::array<PyramidLevel, k_max_levels> level {};
35 uint32_t levels { 0 };
36 uint32_t atlas_w { 0 };
37 uint32_t atlas_h { 0 };
38
39 /**
40 * @brief Layouts are equal when they describe the same atlas for the same
41 * base extent; every other field follows from those.
42 */
43 [[nodiscard]] bool operator==(const PyramidLayout& other) const noexcept
44 {
45 return levels == other.levels && atlas_w == other.atlas_w && atlas_h == other.atlas_h
46 && level[0].w == other.level[0].w && level[0].h == other.level[0].h;
47 }
48};
49
50/**
51 * @brief Place up to @p requested pyramid levels for a w x h base image.
52 *
53 * Levels stop early when the next one would have a side under @p min_extent,
54 * so small images get fewer levels rather than degenerate ones. @p requested
55 * is clamped to [1, PyramidLayout::k_max_levels].
56 *
57 * @param w Base width in pixels.
58 * @param h Base height in pixels.
59 * @param requested Desired number of levels including the base.
60 * @param min_extent Smallest side a level may have.
61 * @return Layout with level 0 at the origin and the rest stacked to its right.
62 */
63[[nodiscard]] inline PyramidLayout pyramid_layout(
64 uint32_t w, uint32_t h, uint32_t requested, uint32_t min_extent = 16)
65{
66 PyramidLayout layout;
67 layout.level[0] = { .ox = 0, .oy = 0, .w = w, .h = h };
68
69 const uint32_t wanted = std::clamp(requested, 1U, PyramidLayout::k_max_levels);
70 uint32_t count = 1;
71 uint32_t column_h = 0;
72 uint32_t column_w = 0;
73
74 while (count < wanted) {
75 const auto& above = layout.level[count - 1];
76 const uint32_t lw = (above.w + 1U) / 2U;
77 const uint32_t lh = (above.h + 1U) / 2U;
78 if (std::min(lw, lh) < min_extent)
79 break;
80
81 layout.level[count] = { .ox = w, .oy = column_h, .w = lw, .h = lh };
82 column_h += lh;
83 column_w = std::max(column_w, lw);
84 ++count;
85 }
86
87 layout.levels = count;
88 layout.atlas_w = w + column_w;
89 layout.atlas_h = std::max(h, column_h);
90 return layout;
91}
92
93} // namespace MayaFlux::Kinesis::Vision
uint32_t h
Definition InkPress.cpp:29
size_t count
PyramidLayout pyramid_layout(uint32_t w, uint32_t h, uint32_t requested, uint32_t min_extent=16)
Place up to requested pyramid levels for a w x h base image.
Definition Pyramid.hpp:63
bool operator==(const PyramidLayout &other) const noexcept
Layouts are equal when they describe the same atlas for the same base extent; every other field follo...
Definition Pyramid.hpp:43
std::array< PyramidLevel, k_max_levels > level
Definition Pyramid.hpp:34
static constexpr uint32_t k_max_levels
Definition Pyramid.hpp:32
Placement of every pyramid level in a single atlas.
Definition Pyramid.hpp:31
Extent and position of one pyramid level inside an atlas.
Definition Pyramid.hpp:17