55 if (bottom.width() != middle.width() || bottom.height() != middle.height() || bottom.width() != top.width() ||
56 bottom.height() != top.height()) {
58 "layer images have mismatched dimensions: bottom={}x{}, middle={}x{}, top={}x{}",
68 const auto bottom_tiles_result = tileizer_.tileize(bottom);
69 if (!bottom_tiles_result.has_value()) {
73 const auto &bottom_tiles = bottom_tiles_result.value();
75 const auto middle_tiles_result = tileizer_.tileize(middle);
76 if (!middle_tiles_result.has_value()) {
80 const auto &middle_tiles = middle_tiles_result.value();
82 const auto top_tiles_result = tileizer_.tileize(top);
83 if (!top_tiles_result.has_value()) {
87 const auto &top_tiles = top_tiles_result.value();
97 "image dimensions must be multiples of {}, got {}x{}",
105 const std::size_t total_metatiles = metatiles_per_row * metatiles_per_col;
107 std::vector<Metatile<T>> metatiles;
108 metatiles.reserve(total_metatiles);
113 for (std::size_t metatile_row = 0; metatile_row < metatiles_per_col; ++metatile_row) {
114 for (std::size_t metatile_col = 0; metatile_col < metatiles_per_row; ++metatile_col) {
116 populate_metatile_at_position(
117 metatile, bottom_tiles, middle_tiles, top_tiles, metatile_row, metatile_col, tiles_per_image_row);
118 metatiles.push_back(std::move(metatile));
146 if (metatiles_per_row == 0) {
147 panic(
"metatiles_per_row must be greater than zero");
150 if (metatiles.empty()) {
155 const std::size_t metatiles_per_col = (metatiles.size() + metatiles_per_row - 1) / metatiles_per_row;
162 Image<T> bottom_image{image_width, image_height};
163 Image<T> middle_image{image_width, image_height};
164 Image<T> top_image{image_width, image_height};
167 for (std::size_t metatile_row = 0; metatile_row < metatiles_per_col; ++metatile_row) {
168 for (std::size_t metatile_col = 0; metatile_col < metatiles_per_row; ++metatile_col) {
169 const std::size_t metatile_idx = metatile_row * metatiles_per_row + metatile_col;
172 if (metatile_idx < metatiles.size()) {
173 const auto &metatile = metatiles[metatile_idx];
174 copy_metatile_to_images(
175 metatile, bottom_image, middle_image, top_image, metatile_row, metatile_col);
178 fill_region_with_transparent(bottom_image, middle_image, top_image, metatile_row, metatile_col);
183 return std::make_tuple(std::move(bottom_image), std::move(middle_image), std::move(top_image));
189 static void populate_metatile_at_position(
194 std::size_t metatile_row,
195 std::size_t metatile_col,
196 std::size_t tiles_per_image_row)
206 const std::size_t global_tile_idx = global_tile_row * tiles_per_image_row + global_tile_col;
209 metatile.
set_bottom(tile_idx, bottom_tiles[global_tile_idx]);
210 metatile.
set_middle(tile_idx, middle_tiles[global_tile_idx]);
211 metatile.
set_top(tile_idx, top_tiles[global_tile_idx]);
215 static void copy_metatile_to_images(
216 const Metatile<T> &metatile,
217 Image<T> &bottom_image,
218 Image<T> &middle_image,
220 std::size_t metatile_row,
221 std::size_t metatile_col)
230 const std::size_t start_pixel_row =
232 const std::size_t start_pixel_col =
236 const auto &bottom_tile = metatile.bottom(tile_idx);
237 const auto &middle_tile = metatile.middle(tile_idx);
238 const auto &top_tile = metatile.top(tile_idx);
242 const std::size_t image_row = start_pixel_row + pixel_row;
243 const std::size_t image_col = start_pixel_col + pixel_col;
245 bottom_image.set(image_row, image_col, bottom_tile.at(pixel_row, pixel_col));
246 middle_image.set(image_row, image_col, middle_tile.at(pixel_row, pixel_col));
247 top_image.set(image_row, image_col, top_tile.at(pixel_row, pixel_col));
253 static void fill_region_with_transparent(
254 Image<T> &bottom_image,
255 Image<T> &middle_image,
257 std::size_t metatile_row,
258 std::size_t metatile_col)
260 const T transparent_pixel{};
268 bottom_image.set(image_row, image_col, transparent_pixel);
269 middle_image.set(image_row, image_col, transparent_pixel);
270 top_image.set(image_row, image_col, transparent_pixel);
A result type that maintains a chainable sequence of errors for debugging and error reporting.
Service for converting images into collections of 8x8 tiles.
A template for two-dimensional images with arbitrarily typed pixel values.
An 8x8 tile backed by literal-array-based per-pixel storage of an arbitrary pixel type.
constexpr std::size_t side_length_pix
void panic(const StringViewSourceLoc &s)
Unconditionally terminates the program with a panic message.