Go to the documentation of this file.
31 #include "table/strings.h"
74 #define MKCOLOUR(x) TO_LE32X(x)
81 PACK(
struct BitmapFileHeader {
87 static_assert(
sizeof(BitmapFileHeader) == 14);
93 uint16 planes, bitcount;
94 uint32 compression, sizeimage, xpels, ypels, clrused, clrimp;
100 byte blue, green, red, reserved;
102 static_assert(
sizeof(
RgbQuad) == 4);
119 switch (pixelformat) {
120 case 8: bpp = 1;
break;
122 case 32: bpp = 3;
break;
124 default:
return false;
127 FILE *f = fopen(name,
"wb");
128 if (f ==
nullptr)
return false;
131 uint bytewidth =
Align(w * bpp, 4);
134 uint pal_size = pixelformat == 8 ?
sizeof(
RgbQuad) * 256 : 0;
137 BitmapFileHeader bfh;
138 bfh.type = TO_LE16(
'MB');
139 bfh.size = TO_LE32(
sizeof(BitmapFileHeader) +
sizeof(
BitmapInfoHeader) + pal_size + bytewidth * h);
141 bfh.off_bits = TO_LE32(
sizeof(BitmapFileHeader) +
sizeof(
BitmapInfoHeader) + pal_size);
146 bih.width = TO_LE32(w);
147 bih.height = TO_LE32(h);
148 bih.planes = TO_LE16(1);
149 bih.bitcount = TO_LE16(bpp * 8);
158 if (fwrite(&bfh,
sizeof(bfh), 1, f) != 1 || fwrite(&bih,
sizeof(bih), 1, f) != 1) {
163 if (pixelformat == 8) {
166 for (uint i = 0; i < 256; i++) {
167 rq[i].red = palette[i].r;
168 rq[i].green = palette[i].g;
169 rq[i].blue = palette[i].b;
173 if (fwrite(rq,
sizeof(rq), 1, f) != 1) {
180 uint maxlines =
Clamp(65536 / (w * pixelformat / 8), 16, 128);
182 uint8 *buff = MallocT<uint8>(maxlines * w * pixelformat / 8);
183 uint8 *line =
AllocaM(uint8, bytewidth);
184 memset(line, 0, bytewidth);
188 uint n = std::min(h, maxlines);
192 callb(userdata, buff, h, w, n);
196 if (pixelformat == 8) {
198 memcpy(line, buff + n * w, w);
204 for (uint i = 0; i < w; i++) {
205 dst[i * 3 ] = src[i].b;
206 dst[i * 3 + 1] = src[i].g;
207 dst[i * 3 + 2] = src[i].r;
211 if (fwrite(line, bytewidth, 1, f) != 1) {
228 #if defined(WITH_PNG)
231 #ifdef PNG_TEXT_SUPPORTED
239 static void PNGAPI png_my_error(png_structp png_ptr, png_const_charp message)
241 Debug(misc, 0,
"[libpng] error: {} - {}", message, (
const char *)png_get_error_ptr(png_ptr));
242 longjmp(png_jmpbuf(png_ptr), 1);
245 static void PNGAPI png_my_warning(png_structp png_ptr, png_const_charp message)
247 Debug(misc, 1,
"[libpng] warning: {} - {}", message, (
const char *)png_get_error_ptr(png_ptr));
268 uint bpp = pixelformat / 8;
273 if (pixelformat != 8 && pixelformat != 32)
return false;
275 f = fopen(name,
"wb");
276 if (f ==
nullptr)
return false;
278 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
const_cast<char *
>(name), png_my_error, png_my_warning);
280 if (png_ptr ==
nullptr) {
285 info_ptr = png_create_info_struct(png_ptr);
286 if (info_ptr ==
nullptr) {
287 png_destroy_write_struct(&png_ptr, (png_infopp)
nullptr);
292 if (setjmp(png_jmpbuf(png_ptr))) {
293 png_destroy_write_struct(&png_ptr, &info_ptr);
298 png_init_io(png_ptr, f);
300 png_set_filter(png_ptr, 0, PNG_FILTER_NONE);
302 png_set_IHDR(png_ptr, info_ptr, w, h, 8, pixelformat == 8 ? PNG_COLOR_TYPE_PALETTE : PNG_COLOR_TYPE_RGB,
303 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
305 #ifdef PNG_TEXT_SUPPORTED
308 png_text_struct text[2];
309 memset(text, 0,
sizeof(text));
310 text[0].key =
const_cast<char *
>(
"Software");
311 text[0].text =
const_cast<char *
>(_openttd_revision);
312 text[0].text_length = strlen(_openttd_revision);
313 text[0].compression = PNG_TEXT_COMPRESSION_NONE;
326 if (c->ai_info ==
nullptr) {
329 p +=
seprintf(p,
lastof(buf),
"%2i: %s (v%d)\n", (
int)c->index, c->ai_info->GetName(), c->ai_info->GetVersion());
332 text[1].key =
const_cast<char *
>(
"Description");
334 text[1].text_length = p - buf;
335 text[1].compression = PNG_TEXT_COMPRESSION_zTXt;
336 png_set_text(png_ptr, info_ptr, text, 2);
339 if (pixelformat == 8) {
341 for (i = 0; i != 256; i++) {
342 rq[i].red = palette[i].r;
343 rq[i].green = palette[i].g;
344 rq[i].blue = palette[i].b;
347 png_set_PLTE(png_ptr, info_ptr, rq, 256);
350 png_write_info(png_ptr, info_ptr);
351 png_set_flush(png_ptr, 512);
353 if (pixelformat == 32) {
362 png_set_sBIT(png_ptr, info_ptr, &sig_bit);
364 #if TTD_ENDIAN == TTD_LITTLE_ENDIAN
365 png_set_bgr(png_ptr);
366 png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
368 png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
373 maxlines =
Clamp(65536 / w, 16, 128);
376 void *buff = CallocT<uint8>(w * maxlines * bpp);
381 n = std::min(h - y, maxlines);
384 callb(userdata, buff, y, w, n);
388 for (i = 0; i != n; i++) {
389 png_write_row(png_ptr, (png_bytep)buff + i * w * bpp);
393 png_write_end(png_ptr, info_ptr);
394 png_destroy_write_struct(&png_ptr, &info_ptr);
416 byte pal_small[16 * 3];
447 if (pixelformat == 32) {
448 Debug(misc, 0,
"Can't convert a 32bpp screenshot to PCX format. Please pick another format.");
451 if (pixelformat != 8 || w == 0)
return false;
453 f = fopen(name,
"wb");
454 if (f ==
nullptr)
return false;
456 memset(&pcx, 0,
sizeof(pcx));
459 pcx.manufacturer = 10;
463 pcx.xmax = TO_LE16(w - 1);
464 pcx.ymax = TO_LE16(h - 1);
465 pcx.hdpi = TO_LE16(320);
466 pcx.vdpi = TO_LE16(320);
469 pcx.cpal = TO_LE16(1);
470 pcx.width = pcx.pitch = TO_LE16(w);
471 pcx.height = TO_LE16(h);
474 if (fwrite(&pcx,
sizeof(pcx), 1, f) != 1) {
480 maxlines =
Clamp(65536 / w, 16, 128);
483 uint8 *buff = CallocT<uint8>(w * maxlines);
488 uint n = std::min(h - y, maxlines);
492 callb(userdata, buff, y, w, n);
496 for (i = 0; i != n; i++) {
497 const uint8 *bufp = buff + i * w;
498 byte runchar = bufp[0];
503 for (j = 1; j < w; j++) {
506 if (ch != runchar || runcount >= 0x3f) {
507 if (runcount > 1 || (runchar & 0xC0) == 0xC0) {
508 if (fputc(0xC0 | runcount, f) == EOF) {
514 if (fputc(runchar, f) == EOF) {
526 if (runcount > 1 || (runchar & 0xC0) == 0xC0) {
527 if (fputc(0xC0 | runcount, f) == EOF) {
533 if (fputc(runchar, f) == EOF) {
544 if (fputc(12, f) == EOF) {
552 for (uint i = 0; i < 256; i++) {
553 tmp[i * 3 + 0] = palette[i].r;
554 tmp[i * 3 + 1] = palette[i].g;
555 tmp[i * 3 + 2] = palette[i].b;
557 success = fwrite(tmp,
sizeof(tmp), 1, f) == 1;
570 #if defined(WITH_PNG)
604 void *src = blitter->
MoveTo(_screen.dst_ptr, 0, y);
626 _screen.dst_ptr = buf;
627 _screen.width = pitch;
629 _screen.pitch = pitch;
637 dpi.width = vp->
width;
645 while (vp->
width - left != 0) {
646 wx = std::min(vp->
width - left, 1600);
660 _screen = old_screen;
671 static const char *
MakeScreenshotName(
const char *default_fn,
const char *ext,
bool crashlog =
false)
689 for (uint serial = 1;; serial++) {
695 if (!generate)
break;
724 assert(width == 0 && height == 0);
735 vp->
width = _screen.width;
736 vp->
height = _screen.height;
741 assert(width == 0 && height == 0);
764 vp->overlay =
nullptr;
774 if (width == 0 || height == 0) {
787 vp->overlay =
nullptr;
821 byte *buf = (
byte *)buffer;
824 for (uint x =
MapMaxX();
true; x--) {
842 for (uint i = 0; i <
lengthof(palette); i++) {
883 uint64_t width = (heightmap_or_minimap ?
MapSizeX() : vp.
width);
884 uint64_t height = (heightmap_or_minimap ?
MapSizeY() : vp.
height);
886 if (width * height > 8192 * 8192) {
1025 static void MinimapScreenCallback(
void *userdata,
void *buf, uint y, uint pitch, uint n)
1040 uint32 *ubuf = (uint32 *)buf;
1041 uint num = (pitch * n);
1042 for (uint i = 0; i < num; i++) {
1043 uint row = y + (int)(i / pitch);
1044 uint col = (
MapSizeX() - 1) - (i % pitch);
1048 byte val = owner_colours[o];
1050 uint32 colour_buf = 0;
@ MP_HOUSE
A house by a town.
Format of palette data in BMP header.
uint32 TileIndex
The index/ID of a Tile.
void SetupScreenshotViewport(ScreenshotType t, Viewport *vp, uint32 width, uint32 height)
Configure a Viewport for rendering (a part of) the map into a screenshot.
static Owner GetMinimapOwner(TileIndex tile)
Return the owner of a tile to display it with in the small map in mode "Owner".
ScreenshotType
Type of requested screenshot.
std::string _personal_dir
custom directory for personal settings, saves, newgrf, etc.
@ WL_WARNING
Other information.
static const uint8 PC_DARK_RED
Dark red palette colour.
static void HeightmapCallback(void *userdata, void *buffer, uint y, uint pitch, uint n)
Callback for generating a heightmap.
std::mutex lock
synchronization for playback status fields
How all blitters should look like.
static uint TilePixelHeight(TileIndex tile)
Returns the height of a tile in pixels.
int width
Screen width of the viewport.
@ SC_HEIGHTMAP
Heightmap of the world.
static Point RemapCoords(int x, int y, int z)
Map 3D world or tile coordinate to equivalent 2D coordinate as used in the viewports and smallmap.
ViewportData * viewport
Pointer to viewport data, if present.
virtual uint8 GetScreenDepth()=0
Get the screen depth this blitter works for.
int height
Screen height of the viewport.
int top
Screen coordinate top edge of the viewport.
Window * FindWindowById(WindowClass cls, WindowNumber number)
Find a window by its class and window number.
std::string _screenshot_format_name
Extension of the current screenshot format (corresponds with _cur_screenshot_format).
static const uint TILE_SIZE
Tile size in world coordinates.
uint32 version
The version of this base set.
ClientSettings _settings_client
The current settings for this game.
@ SC_ZOOMEDIN
Fully zoomed in screenshot of the visible area.
@ MP_INDUSTRY
Part of an industry.
static uint TileY(TileIndex tile)
Get the Y component of a tile.
static const uint8 PC_GRASS_LAND
Dark green palette colour for grass land.
int virtual_top
Virtual top coordinate.
Owner
Enum for all companies/owners.
byte _colour_gradient[COLOUR_END][8]
All 16 colour gradients 8 colours per gradient from darkest (0) to lightest (7)
static void SetDParam(uint n, uint64 v)
Set a string parameter v at index n in the global string parameter array.
bool MakeHeightmapScreenshot(const char *filename)
Make a heightmap of the current map.
void InitializeScreenshotFormats()
Initialize screenshot format information on startup, with _screenshot_format_name filled from the loa...
static uint TileX(TileIndex tile)
Get the X component of a tile.
void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, WarningLevel wl, int x=0, int y=0, const GRFFile *textref_stack_grffile=nullptr, uint textref_stack_size=0, const uint32 *textref_stack=nullptr)
Display an error message in a window.
static uint MapSizeX()
Get the size of the map along the X.
static ScreenshotType _confirmed_screenshot_type
Screenshot type the current query is about to confirm.
Data structure for viewport, display of a part of the world.
static char _screenshot_name[128]
Filename of the screenshot file.
static uint MapSize()
Get the size of the map.
static T Align(const T x, uint n)
Return the smallest multiple of n equal or greater than x.
static uint TileHeight(TileIndex tile)
Returns the height of a tile.
Information about GRF, used in the game and (part of it) in savegames.
int virtual_left
Virtual left coordinate.
bool _screen_disable_anim
Disable palette animation (important for 32bpp-anim blitter during giant screenshot)
int left
Screen coordinate left edge of the viewport.
Colour palette[256]
Current palette. Entry 0 has to be always fully transparent!
bool FileExists(const std::string &filename)
Test whether the given filename exists.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
static Blitter * GetCurrentBlitter()
Get the current active blitter (always set by calling SelectBlitter).
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
bool ScreenshotHandlerProc(const char *name, ScreenshotCallback *callb, void *userdata, uint w, uint h, int pixelformat, const Colour *palette)
Function signature for a screenshot generation routine for one of the available formats.
bool freeform_edges
allow terraforming the tiles at the map edges
static bool StrEmpty(const char *s)
Check if a string buffer is empty.
void DrawDirtyBlocks()
Repaints the rectangle blocks which are marked as 'dirty'.
void ScreenshotCallback(void *userdata, void *buf, uint y, uint pitch, uint n)
Callback function signature for generating lines of pixel data to be written to the screenshot file.
uint _num_screenshot_formats
Number of available screenshot formats.
static void CurrentScreenCallback(void *userdata, void *buf, uint y, uint pitch, uint n)
Callback of the screenshot generator that dumps the current video buffer.
static const char * MakeScreenshotName(const char *default_fn, const char *ext, bool crashlog=false)
Construct a pathname for a screenshot file.
int virtual_width
width << zoom
@ ZOOM_LVL_WORLD_SCREENSHOT
Default zoom level for the world screen shot.
static uint MapSizeY()
Get the size of the map along the Y.
void QueueOnMainThread(std::function< void()> &&func)
Queue a function to be called on the main thread with game state lock held and video buffer locked.
static int UnScaleByZoom(int value, ZoomLevel zoom)
Scale by zoom level, usually shift right (when zoom > ZOOM_LVL_NORMAL) When shifting right,...
static const uint8 PC_BLACK
Black palette colour.
@ ZOOM_LVL_VIEWPORT
Default zoom level for viewports.
static uint32 BSWAP32(uint32 x)
Perform a 32 bits endianness bitswap on x.
static VideoDriver * GetInstance()
Get the currently active instance of the video driver.
virtual void CopyImageToBuffer(const void *video, void *dst, int width, int height, int dst_pitch)=0
Copy from the screen to a buffer in a palette format for 8bpp and RGBA format for 32bpp.
PACK(struct BitmapFileHeader { uint16 type;uint32 size;uint32 reserved;uint32 off_bits;})
BMP File Header (stored in little endian)
static bool IsTileType(TileIndex tile, TileType type)
Checks if a tile is a given tiletype.
void GenerateDefaultSaveName(char *buf, const char *last)
Fill the buffer with the default name for a savegame or screenshot.
static Owner GetTileOwner(TileIndex tile)
Returns the owner of a tile.
Structure to access the alpha, red, green, and blue channels from a 32 bit number.
ZoomLevel zoom_min
minimum zoom out level
static void LargeWorldCallback(void *userdata, void *buf, uint y, uint pitch, uint n)
generate a large piece of the world
static const ScreenshotFormat _screenshot_formats[]
Available screenshot formats.
void ShowQuery(StringID caption, StringID message, Window *parent, QueryCallbackProc *callback)
Show a modal confirmation window with standard 'yes' and 'no' buttons The window is aligned to the ce...
static bool MakeLargeWorldScreenshot(ScreenshotType t, uint32 width=0, uint32 height=0)
Make a screenshot of the map.
void SetScreenshotWindowVisibility(bool hide)
Set the visibility of the screenshot window when taking a screenshot.
static T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
static bool MakeBMPImage(const char *name, ScreenshotCallback *callb, void *userdata, uint w, uint h, int pixelformat, const Colour *palette)
Generic .BMP writer.
static int ScaleByZoom(int value, ZoomLevel zoom)
Scale by zoom level, usually shift left (when zoom > ZOOM_LVL_NORMAL) When shifting right,...
@ SC_WORLD
World screenshot.
static bool MakePCXImage(const char *name, ScreenshotCallback *callb, void *userdata, uint w, uint h, int pixelformat, const Colour *palette)
Generic .PCX file image writer.
static const char *const HEIGHTMAP_NAME
Default filename of a saved heightmap.
uint8 a
colour channels in LE order
@ MP_VOID
Invisible tiles at the SW and SE border.
virtual void * MoveTo(void *video, int x, int y)=0
Move the destination pointer the requested amount x and y, keeping in mind any pitch and bpp of the r...
static TileIndex TileXY(uint x, uint y)
Returns the TileIndex of a coordinate.
@ COMPANY_SPECTATOR
The client is spectating.
struct GRFConfig * next
NOSAVE: Next item in the linked list.
@ OWNER_NONE
The tile has no ownership.
static bool MakePNGImage(const char *name, ScreenshotCallback *callb, void *userdata, uint w, uint h, int pixelformat, const Colour *palette)
Generic .PNG file image writer.
int CDECL seprintf(char *str, const char *last, const char *format,...)
Safer implementation of snprintf; same as snprintf except:
@ SC_DEFAULTZOOM
Zoomed to default zoom level screenshot of the visible area.
@ OWNER_DEITY
The object is owned by a superuser / goal script.
@ WC_MAIN_WINDOW
Main window; Window numbers:
static bool MakeSmallScreenshot(bool crashlog)
Make a screenshot of the current screen.
@ WL_ERROR
Errors (eg. saving/loading failed)
char _full_screenshot_name[MAX_PATH]
Pathname of the screenshot file.
static uint MapMaxX()
Gets the maximum X coordinate within the map, including MP_VOID.
static const uint8 PC_WATER
Dark blue palette colour for water.
bool MakeMinimapWorldScreenshot()
Make a minimap screenshot.
bool MakeScreenshot(ScreenshotType t, std::string name, uint32 width, uint32 height)
Schedule making a screenshot.
#define TILE_ADDXY(tile, x, y)
Adds a given offset to a tile.
Palette _cur_palette
Current palette.
GRFConfig * _grfconfig
First item in list of current GRF set up.
uint _cur_screenshot_format
Index of the currently selected screenshot format in _screenshot_formats.
#define Debug(name, level, format_string,...)
Ouptut a line of debugging information.
const char * GetCurrentScreenshotExtension()
Get filename extension of current screenshot file format.
#define lengthof(x)
Return the length of an fixed size array.
ZoomLevel zoom
The zoom level of the viewport.
@ SC_VIEWPORT
Screenshot of viewport.
void MakeScreenshotWithConfirm(ScreenshotType t)
Make a screenshot.
@ OWNER_END
Last + 1 owner.
ConstructionSettings construction
construction of things in-game
Data structure for an opened window.
char * md5sumToString(char *buf, const char *last, const uint8 md5sum[16])
Convert the md5sum to a hexadecimal string representation.
static TileType GetTileType(TileIndex tile)
Get the tiletype of a given tile.
@ SC_CRASHLOG
Raw screenshot from blitter buffer.
static const uint8 PC_DARK_GREY
Dark grey palette colour.
int virtual_height
height << zoom
@ SC_MINIMAP
Minimap screenshot.
char * strecpy(char *dst, const char *src, const char *last)
Copies characters from one buffer to another.
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
static const char *const SCREENSHOT_NAME
Default filename of a saved screenshot.
@ OWNER_WATER
The tile/execution is done by "water".
#define lastof(x)
Get the last element of an fixed size array.
uint _heightmap_highest_peak
When saving a heightmap, this contains the highest peak on the map.
Helper struct to ensure the video buffer is locked and ready for drawing.
static bool RealMakeScreenshot(ScreenshotType t, std::string name, uint32 width, uint32 height)
Make a screenshot.
@ OWNER_TOWN
A town owns the tile, or a town is expanding.
void SetDParamStr(uint n, const char *str)
This function is used to "bind" a C string to a OpenTTD dparam slot.
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
GUISettings gui
settings related to the GUI
Data about how and where to blit pixels.
const char * FiosGetScreenshotDir()
Get the directory for screenshots.
static void ScreenshotConfirmationCallback(Window *w, bool confirmed)
Callback on the confirmation window for huge screenshots.
#define AllocaM(T, num_elements)
alloca() has to be called in the parent function, so define AllocaM() as a macro