22#include "table/strings.h"
36static const uint MAX_HEIGHTMAP_SIZE_PIXELS = 256 << 20;
42static_assert(MAX_HEIGHTMAP_SIZE_PIXELS < UINT32_MAX / 8);
55 return (uint64_t)width * height <= MAX_HEIGHTMAP_SIZE_PIXELS &&
64static inline uint8_t
RGBToGrayscale(uint8_t red, uint8_t green, uint8_t blue)
68 return ((red * 19595) + (green * 38470) + (blue * 7471)) / 65536;
82 uint8_t gray_palette[256];
83 png_bytep *row_pointers =
nullptr;
84 bool has_palette = png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE;
85 uint channels = png_get_channels(png_ptr, info_ptr);
94 png_get_PLTE(png_ptr, info_ptr, &palette, &palette_size);
95 for (i = 0; i < palette_size && (palette_size != 16 || all_gray); i++) {
96 all_gray &= palette[i].red == palette[i].green && palette[i].red == palette[i].blue;
97 gray_palette[i] =
RGBToGrayscale(palette[i].red, palette[i].green, palette[i].blue);
106 if (palette_size == 16 && !all_gray) {
107 for (i = 0; i < palette_size; i++) {
108 gray_palette[i] = 256 * i / palette_size;
113 row_pointers = png_get_rows(png_ptr, info_ptr);
116 for (x = 0; x < png_get_image_width(png_ptr, info_ptr); x++) {
117 for (y = 0; y < png_get_image_height(png_ptr, info_ptr); y++) {
118 uint8_t *pixel = &map[y * png_get_image_width(png_ptr, info_ptr) + x];
119 uint x_offset = x * channels;
122 *pixel = gray_palette[row_pointers[y][x_offset]];
123 }
else if (channels == 3) {
125 row_pointers[y][x_offset + 1], row_pointers[y][x_offset + 2]);
127 *pixel = row_pointers[y][x_offset];
138static bool ReadHeightmapPNG(
const char *filename, uint *x, uint *y, std::vector<uint8_t> *map)
140 png_structp png_ptr =
nullptr;
141 png_infop info_ptr =
nullptr;
144 if (!fp.has_value()) {
149 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
nullptr,
nullptr,
nullptr);
150 if (png_ptr ==
nullptr) {
155 info_ptr = png_create_info_struct(png_ptr);
156 if (info_ptr ==
nullptr || setjmp(png_jmpbuf(png_ptr))) {
158 png_destroy_read_struct(&png_ptr, &info_ptr,
nullptr);
162 png_init_io(png_ptr, *fp);
166 png_set_packing(png_ptr);
167 png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_PACKING | PNG_TRANSFORM_STRIP_ALPHA | PNG_TRANSFORM_STRIP_16,
nullptr);
171 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)) {
173 png_destroy_read_struct(&png_ptr, &info_ptr,
nullptr);
177 uint width = png_get_image_width(png_ptr, info_ptr);
178 uint height = png_get_image_height(png_ptr, info_ptr);
182 png_destroy_read_struct(&png_ptr, &info_ptr,
nullptr);
186 if (map !=
nullptr) {
187 map->resize(
static_cast<size_t>(width) * height);
194 png_destroy_read_struct(&png_ptr, &info_ptr,
nullptr);
206 uint8_t gray_palette[256];
208 if (!data.palette.empty()) {
209 bool all_gray =
true;
213 all_gray &= data.palette[i].r == data.palette[i].g && data.palette[i].r == data.palette[i].b;
214 gray_palette[i] =
RGBToGrayscale(data.palette[i].r, data.palette[i].g, data.palette[i].b);
234 gray_palette[1] = 16;
239 for (uint y = 0; y < info.
height; y++) {
240 uint8_t *pixel = &map[y *
static_cast<size_t>(info.
width)];
241 const uint8_t *bitmap = &data.bitmap[y *
static_cast<size_t>(info.
width) * (info.
bpp == 24 ? 3 : 1)];
243 for (uint x = 0; x < info.
width; x++) {
244 if (info.
bpp != 24) {
245 *pixel++ = gray_palette[*bitmap++];
259static bool ReadHeightmapBMP(
const char *filename, uint *x, uint *y, std::vector<uint8_t> *map)
262 if (!f.has_value()) {
271 if (!BmpReadHeader(file, info, data)) {
281 if (map !=
nullptr) {
282 if (!BmpReadBitmap(file, info, data)) {
287 map->resize(
static_cast<size_t>(info.width) * info.height);
307 const uint num_div = 16384;
313 uint row_pad = 0, col_pad = 0;
315 uint img_row, img_col;
320 default: NOT_REACHED();
331 if ((img_width * num_div) / img_height > ((width * num_div) / height)) {
333 img_scale = (width * num_div) / img_width;
334 row_pad = (1 + height - ((img_height * img_scale) / num_div)) / 2;
337 img_scale = (height * num_div) / img_height;
338 col_pad = (1 + width - ((img_width * img_scale) / num_div)) / 2;
347 for (row = 0; row < height; row++) {
348 for (col = 0; col < width; col++) {
350 default: NOT_REACHED();
363 img_row = (((row - row_pad) * num_div) / img_scale);
365 default: NOT_REACHED();
367 img_col = (((width - 1 - col - col_pad) * num_div) / img_scale);
370 img_col = (((col - col_pad) * num_div) / img_scale);
374 assert(img_row < img_height);
375 assert(img_col < img_width);
377 uint heightmap_height = map[img_row * img_width + img_col];
379 if (heightmap_height > 0) {
404 uint8_t current_height;
412 for (row = 0; (uint)row < height; row++) {
413 for (col = 0; (uint)col < width; col++) {
427 if (
TileHeight(tile) >= (uint)current_height + 2) {
440 for (row = height - 1; row >= 0; row--) {
441 for (col = width - 1; col >= 0; col--) {
443 if ((uint)col != width - 1) {
448 if ((uint)row != height - 1) {
456 if (
TileHeight(tile) >= (uint)current_height + 2) {
517 std::vector<uint8_t> map;
538 for (uint row = edge_distance; row <
Map::SizeY() - edge_distance; row++) {
539 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.
@ WL_ERROR
Errors (eg. saving/loading failed)
void ShowErrorMessage(EncodedString &&summary_msg, int x, int y, const CommandCost &cc)
Display an error message in a window.
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.
uint32_t RandomRange(uint32_t limit, const std::source_location location=std::source_location::current())
Pick a random number between 0 and limit - 1, inclusive.
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.
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
Functions related to OTTD's strings.
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 map_height_limit
the maximum allowed heightlevel
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 ;)