* The PNG Heightmap loader. */
| 80 | * The PNG Heightmap loader. |
| 81 | */ |
| 82 | static void ReadHeightmapPNGImageData(std::span<uint8_t> map, png_structp png_ptr, png_infop info_ptr) |
| 83 | { |
| 84 | uint x, y; |
| 85 | uint8_t gray_palette[256]; |
| 86 | png_bytep *row_pointers = nullptr; |
| 87 | bool has_palette = png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE; |
| 88 | uint channels = png_get_channels(png_ptr, info_ptr); |
| 89 | |
| 90 | /* Get palette and convert it to greyscale */ |
| 91 | if (has_palette) { |
| 92 | int i; |
| 93 | int palette_size; |
| 94 | png_color *palette; |
| 95 | bool all_gray = true; |
| 96 | |
| 97 | png_get_PLTE(png_ptr, info_ptr, &palette, &palette_size); |
| 98 | for (i = 0; i < palette_size && (palette_size != 16 || all_gray); i++) { |
| 99 | all_gray &= palette[i].red == palette[i].green && palette[i].red == palette[i].blue; |
| 100 | gray_palette[i] = RGBToGreyscale(palette[i].red, palette[i].green, palette[i].blue); |
| 101 | } |
| 102 | |
| 103 | /** |
| 104 | * For a non-gray palette of size 16 we assume that |
| 105 | * the order of the palette determines the height; |
| 106 | * the first entry is the sea (level 0), the second one |
| 107 | * level 1, etc. |
| 108 | */ |
| 109 | if (palette_size == 16 && !all_gray) { |
| 110 | for (i = 0; i < palette_size; i++) { |
| 111 | gray_palette[i] = 256 * i / palette_size; |
| 112 | } |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | row_pointers = png_get_rows(png_ptr, info_ptr); |
| 117 | |
| 118 | /* Read the raw image data and convert in 8-bit greyscale */ |
| 119 | for (x = 0; x < png_get_image_width(png_ptr, info_ptr); x++) { |
| 120 | for (y = 0; y < png_get_image_height(png_ptr, info_ptr); y++) { |
| 121 | uint8_t *pixel = &map[y * png_get_image_width(png_ptr, info_ptr) + x]; |
| 122 | uint x_offset = x * channels; |
| 123 | |
| 124 | if (has_palette) { |
| 125 | *pixel = gray_palette[row_pointers[y][x_offset]]; |
| 126 | } else if (channels == 3) { |
| 127 | *pixel = RGBToGreyscale(row_pointers[y][x_offset + 0], |
| 128 | row_pointers[y][x_offset + 1], row_pointers[y][x_offset + 2]); |
| 129 | } else { |
| 130 | *pixel = row_pointers[y][x_offset]; |
| 131 | } |
| 132 | } |
| 133 | } |
| 134 | } |
| 135 | |
| 136 | /** |
| 137 | * Reads the heightmap and/or size of the heightmap from a PNG file. |
no test coverage detected