Go to the documentation of this file.
32 #include "table/strings.h"
75 #define MKCOLOUR(x) TO_LE32X(x)
82 PACK(
struct BitmapFileHeader {
88 static_assert(
sizeof(BitmapFileHeader) == 14);
94 uint16 planes, bitcount;
95 uint32 compression, sizeimage, xpels, ypels, clrused, clrimp;
101 byte blue, green, red, reserved;
103 static_assert(
sizeof(
RgbQuad) == 4);
120 switch (pixelformat) {
121 case 8: bpp = 1;
break;
123 case 32: bpp = 3;
break;
125 default:
return false;
128 FILE *f = fopen(name,
"wb");
129 if (f ==
nullptr)
return false;
132 uint bytewidth =
Align(w * bpp, 4);
135 uint pal_size = pixelformat == 8 ?
sizeof(
RgbQuad) * 256 : 0;
138 BitmapFileHeader bfh;
139 bfh.type = TO_LE16(
'MB');
140 bfh.size = TO_LE32(
sizeof(BitmapFileHeader) +
sizeof(
BitmapInfoHeader) + pal_size + bytewidth * h);
142 bfh.off_bits = TO_LE32(
sizeof(BitmapFileHeader) +
sizeof(
BitmapInfoHeader) + pal_size);
147 bih.width = TO_LE32(w);
148 bih.height = TO_LE32(h);
149 bih.planes = TO_LE16(1);
150 bih.bitcount = TO_LE16(bpp * 8);
159 if (fwrite(&bfh,
sizeof(bfh), 1, f) != 1 || fwrite(&bih,
sizeof(bih), 1, f) != 1) {
164 if (pixelformat == 8) {
167 for (uint i = 0; i < 256; i++) {
168 rq[i].red = palette[i].r;
169 rq[i].green = palette[i].g;
170 rq[i].blue = palette[i].b;
174 if (fwrite(rq,
sizeof(rq), 1, f) != 1) {
181 uint maxlines =
Clamp(65536 / (w * pixelformat / 8), 16, 128);
183 uint8 *buff = MallocT<uint8>(maxlines * w * pixelformat / 8);
184 uint8 *line =
AllocaM(uint8, bytewidth);
185 memset(line, 0, bytewidth);
189 uint n = std::min(h, maxlines);
193 callb(userdata, buff, h, w, n);
197 if (pixelformat == 8) {
199 memcpy(line, buff + n * w, w);
205 for (uint i = 0; i < w; i++) {
206 dst[i * 3 ] = src[i].b;
207 dst[i * 3 + 1] = src[i].g;
208 dst[i * 3 + 2] = src[i].r;
212 if (fwrite(line, bytewidth, 1, f) != 1) {
229 #if defined(WITH_PNG)
232 #ifdef PNG_TEXT_SUPPORTED
240 static void PNGAPI png_my_error(png_structp png_ptr, png_const_charp message)
242 Debug(misc, 0,
"[libpng] error: {} - {}", message, (
const char *)png_get_error_ptr(png_ptr));
243 longjmp(png_jmpbuf(png_ptr), 1);
246 static void PNGAPI png_my_warning(png_structp png_ptr, png_const_charp message)
248 Debug(misc, 1,
"[libpng] warning: {} - {}", message, (
const char *)png_get_error_ptr(png_ptr));
269 uint bpp = pixelformat / 8;
274 if (pixelformat != 8 && pixelformat != 32)
return false;
276 f = fopen(name,
"wb");
277 if (f ==
nullptr)
return false;
279 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
const_cast<char *
>(name), png_my_error, png_my_warning);
281 if (png_ptr ==
nullptr) {
286 info_ptr = png_create_info_struct(png_ptr);
287 if (info_ptr ==
nullptr) {
288 png_destroy_write_struct(&png_ptr, (png_infopp)
nullptr);
293 if (setjmp(png_jmpbuf(png_ptr))) {
294 png_destroy_write_struct(&png_ptr, &info_ptr);
299 png_init_io(png_ptr, f);
301 png_set_filter(png_ptr, 0, PNG_FILTER_NONE);
303 png_set_IHDR(png_ptr, info_ptr, w, h, 8, pixelformat == 8 ? PNG_COLOR_TYPE_PALETTE : PNG_COLOR_TYPE_RGB,
304 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
306 #ifdef PNG_TEXT_SUPPORTED
309 png_text_struct text[2];
310 memset(text, 0,
sizeof(text));
311 text[0].key =
const_cast<char *
>(
"Software");
312 text[0].text =
const_cast<char *
>(_openttd_revision);
313 text[0].text_length = strlen(_openttd_revision);
314 text[0].compression = PNG_TEXT_COMPRESSION_NONE;
327 if (c->ai_info ==
nullptr) {
330 p +=
seprintf(p,
lastof(buf),
"%2i: %s (v%d)\n", (
int)c->index, c->ai_info->GetName(), c->ai_info->GetVersion());
333 text[1].key =
const_cast<char *
>(
"Description");
335 text[1].text_length = p - buf;
336 text[1].compression = PNG_TEXT_COMPRESSION_zTXt;
337 png_set_text(png_ptr, info_ptr, text, 2);
340 if (pixelformat == 8) {
342 for (i = 0; i != 256; i++) {
343 rq[i].red = palette[i].r;
344 rq[i].green = palette[i].g;
345 rq[i].blue = palette[i].b;
348 png_set_PLTE(png_ptr, info_ptr, rq, 256);
351 png_write_info(png_ptr, info_ptr);
352 png_set_flush(png_ptr, 512);
354 if (pixelformat == 32) {
363 png_set_sBIT(png_ptr, info_ptr, &sig_bit);
365 #if TTD_ENDIAN == TTD_LITTLE_ENDIAN
366 png_set_bgr(png_ptr);
367 png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
369 png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
374 maxlines =
Clamp(65536 / w, 16, 128);
377 void *buff = CallocT<uint8>(w * maxlines * bpp);
382 n = std::min(h - y, maxlines);
385 callb(userdata, buff, y, w, n);
389 for (i = 0; i != n; i++) {
390 png_write_row(png_ptr, (png_bytep)buff + i * w * bpp);
394 png_write_end(png_ptr, info_ptr);
395 png_destroy_write_struct(&png_ptr, &info_ptr);
417 byte pal_small[16 * 3];
448 if (pixelformat == 32) {
449 Debug(misc, 0,
"Can't convert a 32bpp screenshot to PCX format. Please pick another format.");
452 if (pixelformat != 8 || w == 0)
return false;
454 f = fopen(name,
"wb");
455 if (f ==
nullptr)
return false;
457 memset(&pcx, 0,
sizeof(pcx));
460 pcx.manufacturer = 10;
464 pcx.xmax = TO_LE16(w - 1);
465 pcx.ymax = TO_LE16(h - 1);
466 pcx.hdpi = TO_LE16(320);
467 pcx.vdpi = TO_LE16(320);
470 pcx.cpal = TO_LE16(1);
471 pcx.width = pcx.pitch = TO_LE16(w);
472 pcx.height = TO_LE16(h);
475 if (fwrite(&pcx,
sizeof(pcx), 1, f) != 1) {
481 maxlines =
Clamp(65536 / w, 16, 128);
484 uint8 *buff = CallocT<uint8>(w * maxlines);
489 uint n = std::min(h - y, maxlines);
493 callb(userdata, buff, y, w, n);
497 for (i = 0; i != n; i++) {
498 const uint8 *bufp = buff + i * w;
499 byte runchar = bufp[0];
504 for (j = 1; j < w; j++) {
507 if (ch != runchar || runcount >= 0x3f) {
508 if (runcount > 1 || (runchar & 0xC0) == 0xC0) {
509 if (fputc(0xC0 | runcount, f) == EOF) {
515 if (fputc(runchar, f) == EOF) {
527 if (runcount > 1 || (runchar & 0xC0) == 0xC0) {
528 if (fputc(0xC0 | runcount, f) == EOF) {
534 if (fputc(runchar, f) == EOF) {
545 if (fputc(12, f) == EOF) {
553 for (uint i = 0; i < 256; i++) {
554 tmp[i * 3 + 0] = palette[i].r;
555 tmp[i * 3 + 1] = palette[i].g;
556 tmp[i * 3 + 2] = palette[i].b;
558 success = fwrite(tmp,
sizeof(tmp), 1, f) == 1;
571 #if defined(WITH_PNG)
605 void *src = blitter->
MoveTo(_screen.dst_ptr, 0, y);
627 _screen.dst_ptr = buf;
628 _screen.width = pitch;
630 _screen.pitch = pitch;
638 dpi.width = vp->
width;
646 while (vp->
width - left != 0) {
647 wx = std::min(vp->
width - left, 1600);
661 _screen = old_screen;
672 static const char *
MakeScreenshotName(
const char *default_fn,
const char *ext,
bool crashlog =
false)
698 for (uint serial = 1;; serial++) {
704 if (!generate)
break;
733 assert(width == 0 && height == 0);
744 vp->
width = _screen.width;
745 vp->
height = _screen.height;
750 assert(width == 0 && height == 0);
773 vp->overlay =
nullptr;
783 if (width == 0 || height == 0) {
796 vp->overlay =
nullptr;
830 byte *buf = (
byte *)buffer;
833 for (uint x =
MapMaxX();
true; x--) {
851 for (uint i = 0; i <
lengthof(palette); i++) {
892 uint64_t width = (heightmap_or_minimap ?
MapSizeX() : vp.
width);
893 uint64_t height = (heightmap_or_minimap ?
MapSizeY() : vp.
height);
895 if (width * height > 8192 * 8192) {
1007 static void MinimapScreenCallback(
void *userdata,
void *buf, uint y, uint pitch, uint n)
1009 uint32 *ubuf = (uint32 *)buf;
1010 uint num = (pitch * n);
1011 for (uint i = 0; i < num; i++) {
1012 uint row = y + (int)(i / pitch);
1013 uint col = (
MapSizeX() - 1) - (i % pitch);
1018 uint32 colour_buf = 0;
Format of palette data in BMP header.
void SetupScreenshotViewport(ScreenshotType t, Viewport *vp, uint32 width, uint32 height)
Configure a Viewport for rendering (a part of) the map into a screenshot.
ScreenshotType
Type of requested screenshot.
std::string _personal_dir
custom directory for personal settings, saves, newgrf, etc.
@ WL_WARNING
Other information.
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.
static uint TileY(TileIndex tile)
Get the Y component of a tile.
int virtual_top
Virtual top coordinate.
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,...
@ 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)
bool StrEndsWith(const std::string_view str, const std::string_view suffix)
Check whether the given string ends with the given suffix.
void GenerateDefaultSaveName(char *buf, const char *last)
Fill the buffer with the default name for a savegame or screenshot.
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.
uint32 GetSmallMapOwnerPixels(TileIndex tile, TileType t, IncludeHeightmap include_heightmap)
Return the colour a tile would be displayed with in the small map in mode "Owner".
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
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.
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.
@ 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.
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.
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.
@ Never
Never include the heightmap.
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.
#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.
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