shithub: choc

Download patch

ref: 7d8526e3ba91fef73e5c6129cce9a629cb3c8bb4
parent: a8029480188a1b02f4acffc33ef4cfb1b94aecc1
parent: dccc76cfd0dda5b6756372451c5738cc129d3e85
author: Simon Howard <fraggle+github@gmail.com>
date: Mon Mar 17 10:03:10 EDT 2014

Merge pull request #361 from fabiangreffrath/png_screenshots

Allow for PNG screenshots.

--- a/configure.ac
+++ b/configure.ac
@@ -80,6 +80,14 @@
     [
         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])
--- a/src/doom/g_game.c
+++ b/src/doom/g_game.c
@@ -870,7 +870,7 @@
 	    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; 
--- a/src/heretic/g_game.c
+++ b/src/heretic/g_game.c
@@ -930,7 +930,7 @@
                 G_DoPlayDemo();
                 break;
             case ga_screenshot:
-                V_ScreenShot("HTIC%02i.pcx");
+                V_ScreenShot("HTIC%02i.%s");
                 gameaction = ga_nothing;
                 break;
             case ga_completed:
--- a/src/hexen/g_game.c
+++ b/src/hexen/g_game.c
@@ -934,7 +934,7 @@
                 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;
--- a/src/i_video.c
+++ b/src/i_video.c
@@ -178,6 +178,10 @@
 
 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 @@
     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
--- a/src/m_config.c
+++ b/src/m_config.c
@@ -814,6 +814,12 @@
     CONFIG_VARIABLE_INT(show_endoom),
 
     //!
+    // If non-zero, save screenshots in PNG format.
+    //
+
+    CONFIG_VARIABLE_INT(png_screenshots),
+
+    //!
     // @game doom strife
     //
     // If non-zero, the Vanilla savegame limit is enforced; if the
--- a/src/setup/display.c
+++ b/src/setup/display.c
@@ -32,6 +32,7 @@
 #include "mode.h"
 
 #include "display.h"
+#include "config.h"
 
 extern void RestartTextscreen(void);
 
@@ -110,6 +111,7 @@
 
 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 
@@ -561,6 +563,12 @@
                                       &show_endoom));
     }
 
+#ifdef HAVE_LIBPNG
+    TXT_AddWidget(window,
+                  TXT_NewCheckBox("Save screenshots in PNG format",
+                                  &png_screenshots));
+#endif
+
     TXT_SignalConnect(ar_checkbox, "changed", GenerateModesTable, modes_table);
 }
 
@@ -710,6 +718,7 @@
     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
--- a/src/strife/g_game.c
+++ b/src/strife/g_game.c
@@ -937,7 +937,7 @@
             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; 
--- 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 <png.h>
+#endif
+
 // TODO: There are separate RANGECHECK defines for different games, but this
 // is common code. Fix this.
 #define RANGECHECK
@@ -706,7 +711,88 @@
     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);
+        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 +800,25 @@
 {
     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,10 +831,21 @@
         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,
                  W_CacheLumpName (DEH_String("PLAYPAL"), PU_CACHE));
+    }
 }
 
 #define MOUSE_SPEED_BOX_WIDTH  120