21 #include "table/strings.h"
35 static const uint MAX_HEIGHTMAP_SIZE_PIXELS = 256 << 20;
41 static_assert(MAX_HEIGHTMAP_SIZE_PIXELS < UINT32_MAX / 8);
54 return (uint64_t)
width *
height <= MAX_HEIGHTMAP_SIZE_PIXELS &&
63 static inline uint8_t
RGBToGrayscale(uint8_t red, uint8_t green, uint8_t blue)
67 return ((red * 19595) + (green * 38470) + (blue * 7471)) / 65536;
81 uint8_t gray_palette[256];
82 png_bytep *row_pointers =
nullptr;
83 bool has_palette = png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE;
84 uint channels = png_get_channels(png_ptr, info_ptr);
93 png_get_PLTE(png_ptr, info_ptr, &palette, &palette_size);
94 for (i = 0; i < palette_size && (palette_size != 16 || all_gray); i++) {
95 all_gray &= palette[i].red == palette[i].green && palette[i].red == palette[i].blue;
96 gray_palette[i] =
RGBToGrayscale(palette[i].red, palette[i].green, palette[i].blue);
105 if (palette_size == 16 && !all_gray) {
106 for (i = 0; i < palette_size; i++) {
107 gray_palette[i] = 256 * i / palette_size;
112 row_pointers = png_get_rows(png_ptr, info_ptr);
115 for (x = 0; x < png_get_image_width(png_ptr, info_ptr); x++) {
116 for (y = 0; y < png_get_image_height(png_ptr, info_ptr); y++) {
117 uint8_t *pixel = &map[y * png_get_image_width(png_ptr, info_ptr) + x];
118 uint x_offset = x * channels;
121 *pixel = gray_palette[row_pointers[y][x_offset]];
122 }
else if (channels == 3) {
124 row_pointers[y][x_offset + 1], row_pointers[y][x_offset + 2]);
126 *pixel = row_pointers[y][x_offset];
137 static bool ReadHeightmapPNG(
const char *filename, uint *x, uint *y, std::vector<uint8_t> *map)
139 png_structp png_ptr =
nullptr;
140 png_infop info_ptr =
nullptr;
143 if (!fp.has_value()) {
148 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
nullptr,
nullptr,
nullptr);
149 if (png_ptr ==
nullptr) {
154 info_ptr = png_create_info_struct(png_ptr);
155 if (info_ptr ==
nullptr || setjmp(png_jmpbuf(png_ptr))) {
157 png_destroy_read_struct(&png_ptr, &info_ptr,
nullptr);
161 png_init_io(png_ptr, *fp);
165 png_set_packing(png_ptr);
166 png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_PACKING | PNG_TRANSFORM_STRIP_ALPHA | PNG_TRANSFORM_STRIP_16,
nullptr);
170 if ((png_get_channels(png_ptr, info_ptr) != 1) && (png_get_channels(png_ptr, info_ptr) != 3) && (png_get_bit_depth(png_ptr, info_ptr) != 8)) {
172 png_destroy_read_struct(&png_ptr, &info_ptr,
nullptr);
176 uint
width = png_get_image_width(png_ptr, info_ptr);
177 uint
height = png_get_image_height(png_ptr, info_ptr);
181 png_destroy_read_struct(&png_ptr, &info_ptr,
nullptr);
185 if (map !=
nullptr) {
193 png_destroy_read_struct(&png_ptr, &info_ptr,
nullptr);
205 uint8_t gray_palette[256];
207 if (!data.palette.empty()) {
208 bool all_gray =
true;
212 all_gray &= data.palette[i].r == data.palette[i].g && data.palette[i].r == data.palette[i].b;
213 gray_palette[i] =
RGBToGrayscale(data.palette[i].r, data.palette[i].g, data.palette[i].b);
233 gray_palette[1] = 16;
238 for (uint y = 0; y < info.
height; y++) {
239 uint8_t *pixel = &map[y *
static_cast<size_t>(info.
width)];
240 const uint8_t *bitmap = &data.bitmap[y *
static_cast<size_t>(info.
width) * (info.
bpp == 24 ? 3 : 1)];
242 for (uint x = 0; x < info.
width; x++) {
243 if (info.
bpp != 24) {
244 *pixel++ = gray_palette[*bitmap++];
258 static bool ReadHeightmapBMP(
const char *filename, uint *x, uint *y, std::vector<uint8_t> *map)
261 if (!f.has_value()) {
270 if (!BmpReadHeader(file, info, data)) {
280 if (map !=
nullptr) {
281 if (!BmpReadBitmap(file, info, data)) {
286 map->resize(
static_cast<size_t>(info.width) * info.height);
306 const uint num_div = 16384;
312 uint row_pad = 0, col_pad = 0;
314 uint img_row, img_col;
319 default: NOT_REACHED();
330 if ((img_width * num_div) / img_height > ((
width * num_div) /
height)) {
332 img_scale = (
width * num_div) / img_width;
333 row_pad = (1 +
height - ((img_height * img_scale) / num_div)) / 2;
336 img_scale = (
height * num_div) / img_height;
337 col_pad = (1 +
width - ((img_width * img_scale) / num_div)) / 2;
346 for (row = 0; row <
height; row++) {
347 for (col = 0; col <
width; col++) {
349 default: NOT_REACHED();
362 img_row = (((row - row_pad) * num_div) / img_scale);
364 default: NOT_REACHED();
366 img_col = (((
width - 1 - col - col_pad) * num_div) / img_scale);
369 img_col = (((col - col_pad) * num_div) / img_scale);
373 assert(img_row < img_height);
374 assert(img_col < img_width);
376 uint heightmap_height = map[img_row * img_width + img_col];
378 if (heightmap_height > 0) {
403 uint8_t current_tile;
410 for (row = 0; (uint)row <
height; row++) {
411 for (col = 0; (uint)col <
width; col++) {
432 for (row =
height - 1; row >= 0; row--) {
433 for (col =
width - 1; col >= 0; col--) {
435 if ((uint)col !=
width - 1) {
440 if ((uint)row !=
height - 1) {
503 std::vector<uint8_t> map;
524 for (uint row = edge_distance; row <
Map::SizeY() - edge_distance; row++) {
525 for (uint col = edge_distance; col <
Map::SizeX() - edge_distance; col++) {