From 002822dfa2bd78f946b7e4730004220919d4ddb9 Mon Sep 17 00:00:00 2001 From: Fabian Greffrath Date: Mon, 17 Mar 2014 16:42:49 +0100 Subject: Allow for PNG screenshots. --- configure.ac | 8 +++++ src/doom/g_game.c | 2 +- src/heretic/g_game.c | 2 +- src/hexen/g_game.c | 2 +- src/i_video.c | 5 +++ src/m_config.c | 6 ++++ src/setup/display.c | 2 ++ src/strife/g_game.c | 2 +- src/v_video.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++- 9 files changed, 122 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index 90c2752a..04ad2865 100644 --- a/configure.ac +++ b/configure.ac @@ -80,6 +80,14 @@ AC_SDL_MAIN_WORKAROUND([ [ AC_CHECK_LIB(samplerate, src_new) ]) + # Check for libpng. + AC_ARG_WITH([libpng], + AS_HELP_STRING([--without-libpng], + [Build without libpng @<:@default=check@:>@]), + [], + [ + AC_CHECK_LIB(png, png_get_io_ptr) + ]) AC_CHECK_LIB(m, log) AC_CHECK_HEADERS([linux/kd.h dev/isa/spkrio.h dev/speaker/speaker.h]) diff --git a/src/doom/g_game.c b/src/doom/g_game.c index f2be98f8..a36267ca 100644 --- a/src/doom/g_game.c +++ b/src/doom/g_game.c @@ -870,7 +870,7 @@ void G_Ticker (void) G_DoWorldDone (); break; case ga_screenshot: - V_ScreenShot("DOOM%02i.pcx"); + V_ScreenShot("DOOM%02i.%s"); players[consoleplayer].message = DEH_String("screen shot"); gameaction = ga_nothing; break; diff --git a/src/heretic/g_game.c b/src/heretic/g_game.c index 48e68a2a..2ad9f4b3 100644 --- a/src/heretic/g_game.c +++ b/src/heretic/g_game.c @@ -930,7 +930,7 @@ void G_Ticker(void) G_DoPlayDemo(); break; case ga_screenshot: - V_ScreenShot("HTIC%02i.pcx"); + V_ScreenShot("HTIC%02i.%s"); gameaction = ga_nothing; break; case ga_completed: diff --git a/src/hexen/g_game.c b/src/hexen/g_game.c index cb6d7130..4e40f578 100644 --- a/src/hexen/g_game.c +++ b/src/hexen/g_game.c @@ -934,7 +934,7 @@ void G_Ticker(void) G_DoPlayDemo(); break; case ga_screenshot: - V_ScreenShot("HEXEN%02i.pcx"); + V_ScreenShot("HEXEN%02i.%s"); P_SetMessage(&players[consoleplayer], "SCREEN SHOT", false); gameaction = ga_nothing; break; diff --git a/src/i_video.c b/src/i_video.c index 1add5312..d3f674d4 100644 --- a/src/i_video.c +++ b/src/i_video.c @@ -178,6 +178,10 @@ static unsigned int mouse_button_state = 0; int novert = 0; +// Save screenshots in PNG format. + +int png_screenshots = 0; + // if true, I_VideoBuffer is screen->pixels static boolean native_surface; @@ -2220,6 +2224,7 @@ void I_BindVideoVariables(void) M_BindVariable("usegamma", &usegamma); M_BindVariable("vanilla_keyboard_mapping", &vanilla_keyboard_mapping); M_BindVariable("novert", &novert); + M_BindVariable("png_screenshots", &png_screenshots); // Windows Vista or later? Set screen color depth to // 32 bits per pixel, as 8-bit palettized screen modes diff --git a/src/m_config.c b/src/m_config.c index dd15f1af..2bce54bc 100644 --- a/src/m_config.c +++ b/src/m_config.c @@ -1434,6 +1434,12 @@ static default_t extra_defaults_list[] = // CONFIG_VARIABLE_KEY(key_multi_msgplayer8), + + //! + // If non-zero, save screenshots in PNG format. + // + + CONFIG_VARIABLE_INT(png_screenshots), }; static default_collection_t extra_defaults = diff --git a/src/setup/display.c b/src/setup/display.c index 494d732a..99c3d8aa 100644 --- a/src/setup/display.c +++ b/src/setup/display.c @@ -110,6 +110,7 @@ static int usegamma = 0; int graphical_startup = 1; int show_endoom = 1; +int png_screenshots = 0; // These are the last screen width/height values that were chosen by the // user. These are used when finding the "nearest" mode, so when @@ -710,6 +711,7 @@ void BindDisplayVariables(void) M_BindVariable("video_driver", &video_driver); M_BindVariable("window_position", &window_position); M_BindVariable("usegamma", &usegamma); + M_BindVariable("png_screenshots", &png_screenshots); if (gamemission == doom || gamemission == heretic diff --git a/src/strife/g_game.c b/src/strife/g_game.c index 19f3e1fe..dc9ee351 100644 --- a/src/strife/g_game.c +++ b/src/strife/g_game.c @@ -937,7 +937,7 @@ void G_Ticker (void) G_DoWorldDone (); break; case ga_screenshot: - V_ScreenShot("STRIFE%02i.pcx"); // [STRIFE] file name, message + V_ScreenShot("STRIFE%02i.%s"); // [STRIFE] file name, message players[consoleplayer].message = DEH_String("STRIFE by Rogue entertainment"); gameaction = ga_nothing; break; diff --git a/src/v_video.c b/src/v_video.c index 0cf64926..60817086 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -44,6 +44,11 @@ #include "w_wad.h" #include "z_zone.h" +#include "config.h" +#ifdef HAVE_LIBPNG +#include +#endif + // TODO: There are separate RANGECHECK defines for different games, but this // is common code. Fix this. #define RANGECHECK @@ -706,6 +711,81 @@ void WritePCXfile(char *filename, byte *data, Z_Free (pcx); } +#ifdef HAVE_LIBPNG +// +// WritePNGfile +// + +static void error_fn(png_structp p, png_const_charp s) +{ + printf("libpng error: %s\n", s); +} + +static void warning_fn(png_structp p, png_const_charp s) +{ + printf("libpng warning: %s\n", s); +} + +void WritePNGfile(char *filename, byte *data, + int width, int height, + byte *palette) +{ + png_structp ppng; + png_infop pinfo; + png_colorp pcolor; + FILE *handle; + int i; + + handle = fopen(filename, "wb"); + if (!handle) + return; + + ppng = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, + error_fn, warning_fn); + if (!ppng) + return; + + pinfo = png_create_info_struct(ppng); + if (!pinfo) + { + png_destroy_write_struct(&ppng, NULL); + return; + } + + png_init_io(ppng, handle); + + png_set_IHDR(ppng, pinfo, width, height, + 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + pcolor = malloc(sizeof(*pcolor) * 256); + if (!pcolor) + { + png_destroy_write_struct(&ppng, &pinfo); + return; + } + + for (i = 0; i < 256; i++) + { + pcolor[i].red = *(palette + 3 * i + 0); + pcolor[i].green = *(palette + 3 * i + 1); + pcolor[i].blue = *(palette + 3 * i + 2); + } + + png_set_PLTE(ppng, pinfo, pcolor, 256); + free(pcolor); + + png_write_info(ppng, pinfo); + + for (i = 0; i < SCREENHEIGHT; i++) + png_write_row(ppng, data + i*SCREENWIDTH); + + png_write_end(ppng, pinfo); + png_destroy_write_struct(&ppng, &pinfo); + fclose(handle); +} +#endif + // // V_ScreenShot // @@ -714,12 +794,21 @@ void V_ScreenShot(char *format) { int i; char lbmname[16]; // haleyjd 20110213: BUG FIX - 12 is too small! + char *ext; + extern int png_screenshots; // find a file name to save it to +#ifdef HAVE_LIBPNG + if (png_screenshots) + ext = "png"; + else +#endif + ext = "pcx"; + for (i=0; i<=99; i++) { - sprintf(lbmname, format, i); + sprintf(lbmname, format, i, ext); if (!M_FileExists(lbmname)) { @@ -732,6 +821,13 @@ void V_ScreenShot(char *format) I_Error ("V_ScreenShot: Couldn't create a PCX"); } +#ifdef HAVE_LIBPNG + if (png_screenshots) + WritePNGfile(lbmname, I_VideoBuffer, + SCREENWIDTH, SCREENHEIGHT, + W_CacheLumpName (DEH_String("PLAYPAL"), PU_CACHE)); + else +#endif // save the pcx file WritePCXfile(lbmname, I_VideoBuffer, SCREENWIDTH, SCREENHEIGHT, -- cgit v1.2.3