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) {
186 map->resize(
static_cast<size_t>(width) * height);
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++) {
Read and write support for bmps.
A file from which bytes, words and double words are read in (potentially) a random order.
Map accessors for 'clear' tiles.
void MakeClear(Tile t, ClearGround g, uint density)
Make a clear tile.
Functions related to errors.
void ShowErrorMessage(StringID summary_msg, int x, int y, CommandCost cc)
Display an error message in a window.
@ WL_ERROR
Errors (eg. saving/loading failed)
std::optional< FileHandle > FioFOpenFile(const std::string &filename, const char *mode, Subdirectory subdir, size_t *filesize)
Opens a OpenTTD file somewhere in a personal or global directory.
Functions for Standard In/Out file operations.
DetailedFileType
Kinds of files in each AbstractFileType.
@ DFT_HEIGHTMAP_BMP
BMP file.
@ DFT_HEIGHTMAP_PNG
PNG file.
@ HEIGHTMAP_DIR
Subdirectory of scenario for heightmaps.
Declarations for savegames operations.
Functions related to the gfx engine.
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
static const uint MAX_HEIGHTMAP_SIDE_LENGTH_IN_PIXELS
Maximum number of pixels for one dimension of a heightmap image.
static void GrayscaleToMapHeights(uint img_width, uint img_height, std::span< const uint8_t > map)
Converts a given grayscale map to something that fits in OTTD map system and create a map of that dat...
bool LoadHeightmap(DetailedFileType dft, const char *filename)
Load a heightmap from file and change the map in its current dimensions to a landscape representing t...
static uint8_t RGBToGrayscale(uint8_t red, uint8_t green, uint8_t blue)
Convert RGB colours to Grayscale using 29.9% Red, 58.7% Green, 11.4% Blue (average luminosity formula...
bool GetHeightmapDimensions(DetailedFileType dft, const char *filename, uint *x, uint *y)
Get the dimensions of a heightmap.
void FlatEmptyWorld(uint8_t tile_height)
Make an empty world where all tiles are of height 'tile_height'.
static bool ReadHeightmapPNG(const char *filename, uint *x, uint *y, std::vector< uint8_t > *map)
Reads the heightmap and/or size of the heightmap from a PNG file.
static void ReadHeightmapPNGImageData(std::span< uint8_t > map, png_structp png_ptr, png_infop info_ptr)
The PNG Heightmap loader.
static bool IsValidHeightmapDimension(size_t width, size_t height)
Check whether the loaded dimension of the heightmap image are considered valid enough to attempt to l...
void FixSlopes()
This function takes care of the fact that land in OpenTTD can never differ more than 1 in height.
static void ReadHeightmapBMPImageData(std::span< uint8_t > map, const BmpInfo &info, const BmpData &data)
The BMP Heightmap loader.
static bool ReadHeightMap(DetailedFileType dft, const char *filename, uint *x, uint *y, std::vector< uint8_t > *map)
Reads the heightmap with the correct file reader.
static bool ReadHeightmapBMP(const char *filename, uint *x, uint *y, std::vector< uint8_t > *map)
Reads the heightmap and/or size of the heightmap from a BMP file.
Functions related to creating heightmaps from files.
@ HM_CLOCKWISE
Rotate the map clockwise 45 degrees.
@ HM_COUNTER_CLOCKWISE
Rotate the map counter clockwise 45 degrees.
uint DistanceFromEdge(TileIndex tile)
Param the minimum distance to an edge.
static debug_inline TileIndex TileXY(uint x, uint y)
Returns the TileIndex of a coordinate.
static const uint MAX_MAP_SIZE
Maximal map size = 4096.
A number of safeguards to prevent using unsafe methods.
Functions/types related to saving and loading games.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition of base types and functions in a cross-platform compatible way.
uint32_t height
bitmap height
uint32_t width
bitmap width
uint32_t palette_size
number of colours in palette
uint16_t bpp
bits per pixel
bool freeform_edges
allow terraforming the tiles at the map edges
uint8_t heightmap_rotation
rotation director for the heightmap
uint8_t heightmap_height
highest mountain for heightmap (towards what it scales)
ConstructionSettings construction
construction of things in-game
GameCreationSettings game_creation
settings used during the creation of a game (map)
static uint SizeY()
Get the size of the map along the Y.
static debug_inline uint SizeX()
Get the size of the map along the X.
bool IsInnerTile(Tile tile)
Check if a tile is within the map (not a border)
void SetTileHeight(Tile tile, uint height)
Sets the height of a tile.
static debug_inline uint TileHeight(Tile tile)
Returns the height of a tile.
static const uint MAX_TILE_HEIGHT
Maximum allowed tile height.
Map accessors for void tiles.
void MakeVoid(Tile t)
Make a nice void tile ;)