Lagrange
Loading...
Searching...
No Matches
split_grid.h
1/*
2 * Copyright 2026 Adobe. All rights reserved.
3 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License. You may obtain a copy
5 * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 *
7 * Unless required by applicable law or agreed to in writing, software distributed under
8 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 * OF ANY KIND, either express or implied. See the License for the specific language
10 * governing permissions and limitations under the License.
11 */
12#pragma once
13
14#include <lagrange/image/View3D.h>
15#include <lagrange/utils/assert.h>
16#include <lagrange/utils/fmt/format.h>
17
18#include <array>
19#include <cmath>
20#include <limits>
21#include <vector>
22
23namespace lagrange::image::experimental {
24
27
39struct SplitGridOptions
40{
42 size_t num_cells = 0;
43
45 size_t rows = 0;
46
48 size_t cols = 0;
49};
50
66template <typename T>
67std::vector<View3D<T>> split_grid(View3D<T> grid, const SplitGridOptions& options)
68{
69 const size_t grid_width = grid.extent(0);
70 const size_t grid_height = grid.extent(1);
71 const size_t num_channels = grid.extent(2);
72 const size_t num_cells = options.num_cells;
73 la_runtime_assert(num_cells > 0, "num_cells must be greater than 0");
74
75 auto resolve = [&]() -> std::pair<size_t, size_t> {
76 if (options.rows != 0 && options.cols != 0) {
77 return {options.rows, options.cols};
78 }
79 if (options.rows != 0) {
81 num_cells % options.rows == 0,
82 lagrange::format(
83 "Number of cells ({}) is not divisible by rows ({})",
84 num_cells,
85 options.rows));
86 return {options.rows, num_cells / options.rows};
87 }
88 if (options.cols != 0) {
90 num_cells % options.cols == 0,
91 lagrange::format(
92 "Number of cells ({}) is not divisible by cols ({})",
93 num_cells,
94 options.cols));
95 return {num_cells / options.cols, options.cols};
96 }
97 size_t best_rows = 0;
98 size_t best_cols = 0;
99 double best_aspect_diff = std::numeric_limits<double>::max();
100 for (size_t cols = 1; cols <= num_cells; ++cols) {
101 if (num_cells % cols != 0) continue;
102 size_t rows = num_cells / cols;
103 if (grid_width % cols != 0 || grid_height % rows != 0) continue;
104 size_t cell_w = grid_width / cols;
105 size_t cell_h = grid_height / rows;
106 double aspect_diff = std::abs(static_cast<double>(cell_w) / cell_h - 1.0);
107 if (aspect_diff < best_aspect_diff) {
108 best_aspect_diff = aspect_diff;
109 best_rows = rows;
110 best_cols = cols;
111 }
112 }
114 best_cols > 0,
115 lagrange::format(
116 "Cannot evenly divide grid image ({}x{}) into {} cells",
117 grid_width,
118 grid_height,
119 num_cells));
120 return {best_rows, best_cols};
121 };
122
123 auto [rows, cols] = resolve();
125 rows * cols == num_cells,
126 lagrange::format(
127 "Layout {}x{} does not match number of cells ({})",
128 rows,
129 cols,
130 num_cells));
132 grid_width % cols == 0 && grid_height % rows == 0,
133 lagrange::format(
134 "Grid image ({}x{}) is not divisible by layout ({}x{})",
135 grid_width,
136 grid_height,
137 rows,
138 cols));
139
140 const size_t cell_width = grid_width / cols;
141 const size_t cell_height = grid_height / rows;
142
143 std::vector<View3D<T>> views;
144 views.reserve(num_cells);
145 const dextents<size_t, 3> cell_shape{cell_width, cell_height, num_channels};
146 const std::array<size_t, 3> cell_strides{grid.stride(0), grid.stride(1), grid.stride(2)};
147 const layout_stride::mapping<dextents<size_t, 3>> cell_mapping{cell_shape, cell_strides};
148 for (size_t row = 0; row < rows; ++row) {
149 for (size_t col = 0; col < cols; ++col) {
150 T* cell_ptr = &grid(col * cell_width, row * cell_height, 0);
151 views.emplace_back(cell_ptr, cell_mapping);
152 }
153 }
154 return views;
155}
156
158
159} // namespace lagrange::image::experimental
#define la_runtime_assert(...)
Runtime assertion check.
Definition assert.h:175
std::vector< View3D< T > > split_grid(View3D< T > grid, const SplitGridOptions &options)
Definition split_grid.h:67