foxygit / doom Log in
commit 7215d13b6c4f253b6d1752a0fa2d0b9a0d16fc1f
Author:     Jonathan Dowland <jon+github@alcopop.org>
AuthorDate: Thu Jul 14 23:44:16 2016 +0100
Commit:     Jonathan Dowland <jon+github@alcopop.org>
CommitDate: Thu Jul 14 23:57:28 2016 +0100

    Revert using SDL_Image for PNG screenshots

    This reverts commits 901ee2fe7588fd9dbe62f40b187bcaf364c0fce1 and
    07afb7749ff807118431ea356ab56364ef8cfee8.

    This change broke PNG screenshots on OS X and resulted in 32bit PNGs
    on other platforms (large file sizes). The former might be a SDL_Image
    bug, the latter definitely is.

    Fixes #752
---
 configure.ac        |  23 +++++++++--
 src/Makefile.am     |   6 +--
 src/i_video.c       |  25 ------------
 src/i_video.h       |   2 -
 src/setup/display.c |   2 +
 src/v_video.c       | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 6 files changed, 138 insertions(+), 35 deletions(-)

diff --git a/configure.ac b/configure.ac
index 47cb3353..9c2f17c6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -37,7 +37,6 @@ fi
 PKG_CHECK_MODULES(SDL, [sdl2 >= 2.0.1])
 PKG_CHECK_MODULES(SDLMIXER, [SDL2_mixer >= 2.0.0])
 PKG_CHECK_MODULES(SDLNET, [SDL2_net >= 2.0.0])
-PKG_CHECK_MODULES(SDLIMAGE, [SDL2_image >= 2.0.0])

 # Check for libsamplerate.
 AC_ARG_WITH([libsamplerate],
@@ -57,10 +56,28 @@ AS_IF([test "x$with_libsamplerate" != xno], [
     ])
 ])

+# Check for libpng.
+AC_ARG_WITH([libpng],
+AS_HELP_STRING([--without-libpng],
+    [Build without libpng @<:@default=check@:>@]),
+[],
+[
+    [with_libpng=check]
+])
+AS_IF([test "x$with_libpng" != xno], [
+    PKG_CHECK_MODULES(PNG, libpng >= 1.6.10, [
+        AC_DEFINE([HAVE_LIBPNG], [1], [libpng installed])
+    ], [
+        AS_IF([test "x$with_libpng" != xcheck], [AC_MSG_FAILURE(
+            [--with-libpng was given, but test for libpng failed])
+        ])
+    ])
+])
+
 # TODO: We currently link everything against libraries that don't need it.
 # Use the specific library CFLAGS/LIBS variables instead of setting them here.
-CFLAGS="$CFLAGS $SDL_CFLAGS ${SAMPLERATE_CFLAGS:-}"
-LDFLAGS="$LDFLAGS $SDL_LIBS ${SAMPLERATE_LIBS:-}"
+CFLAGS="$CFLAGS $SDL_CFLAGS ${SAMPLERATE_CFLAGS:-} ${PNG_CFLAGS:-}"
+LDFLAGS="$LDFLAGS $SDL_LIBS ${SAMPLERATE_LIBS:-} ${PNG_LIBS:-}"
 AC_CHECK_LIB(m, log)

 AC_CHECK_HEADERS([linux/kd.h dev/isa/spkrio.h dev/speaker/speaker.h])
diff --git a/src/Makefile.am b/src/Makefile.am
index 64e41a4a..8b97f91a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -21,8 +21,7 @@ execgames_SCRIPTS = $(SETUP_BINARIES)
 AM_CFLAGS = -I$(top_srcdir)/textscreen            \
             -I$(top_srcdir)/opl                   \
             -I$(top_srcdir)/pcsound               \
-            @SDLMIXER_CFLAGS@ @SDLNET_CFLAGS@     \
-            @SDLIMAGE_CFLAGS@
+            @SDLMIXER_CFLAGS@ @SDLNET_CFLAGS@

 # Common source files used by absolutely everything:

@@ -152,8 +151,7 @@ EXTRA_LIBS =                                               \
                @LDFLAGS@                                   \
                @SDL_LIBS@                                  \
                @SDLMIXER_LIBS@                             \
-               @SDLNET_LIBS@                               \
-               @SDLIMAGE_LIBS@
+               @SDLNET_LIBS@

 if HAVE_WINDRES
 @PROGRAM_PREFIX@doom_SOURCES=$(SOURCE_FILES_WITH_DEH) resource.rc
diff --git a/src/i_video.c b/src/i_video.c
index b14bf432..bc86aaaf 100644
--- a/src/i_video.c
+++ b/src/i_video.c
@@ -18,7 +18,6 @@


 #include "SDL.h"
-#include "SDL_image.h"
 #include "SDL_opengl.h"

 #ifdef _WIN32
@@ -1284,27 +1283,3 @@ void I_BindVideoVariables(void)
     M_BindIntVariable("usegamma",                  &usegamma);
     M_BindIntVariable("png_screenshots",           &png_screenshots);
 }
-
-void I_SavePNGScreenshot (char *filename)
-{
-    if (aspect_ratio_correct)
-    {
-        const int width = 1600, height = 1200;
-        SDL_Surface *shotbuffer;
-
-        shotbuffer = SDL_CreateRGBSurface(0, width, height, 32,
-                                          0x00ff0000,
-                                          0x0000ff00,
-                                          0x000000ff,
-                                          0xff000000);
-
-        SDL_BlitScaled(rgbabuffer, NULL, shotbuffer, NULL);
-        IMG_SavePNG(shotbuffer, filename);
-
-        SDL_FreeSurface(shotbuffer);
-    }
-    else
-    {
-        IMG_SavePNG(rgbabuffer, filename);
-    }
-}
diff --git a/src/i_video.h b/src/i_video.h
index 591e7809..d4f3bf6d 100644
--- a/src/i_video.h
+++ b/src/i_video.h
@@ -78,8 +78,6 @@ void I_StartTic (void);

 void I_EnableLoadingDisk(int xoffs, int yoffs);

-void I_SavePNGScreenshot (char *filename);
-
 extern char *video_driver;
 extern boolean screenvisible;

diff --git a/src/setup/display.c b/src/setup/display.c
index 75b7ae3f..90480eff 100644
--- a/src/setup/display.c
+++ b/src/setup/display.c
@@ -200,8 +200,10 @@ static void AdvancedDisplayConfig(TXT_UNCAST_ARG(widget),
             || gamemission == strife,
             TXT_NewCheckBox("Show ENDOOM screen on exit",
                             &show_endoom)),
+#ifdef HAVE_LIBPNG
         TXT_NewCheckBox("Save screenshots in PNG format",
                         &png_screenshots),
+#endif
         NULL);

     TXT_SignalConnect(ar_checkbox, "changed", GenerateSizesTable, sizes_table);
diff --git a/src/v_video.c b/src/v_video.c
index 64702316..9d575e03 100644
--- a/src/v_video.c
+++ b/src/v_video.c
@@ -38,6 +38,9 @@
 #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.
@@ -701,6 +704,110 @@ 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 inwidth, int inheight,
+                  byte *palette)
+{
+    png_structp ppng;
+    png_infop pinfo;
+    png_colorp pcolor;
+    FILE *handle;
+    int i, j;
+    int width, height;
+    byte *rowbuf;
+
+    // scale up to accommodate aspect ratio correction
+    width = inwidth * 5;
+    height = inheight * 6;
+
+    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);
+
+    rowbuf = malloc(width);
+
+    if (rowbuf)
+    {
+        for (i = 0; i < SCREENHEIGHT; i++)
+        {
+            // expand the row 5x
+            for (j = 0; j < SCREENWIDTH; j++)
+            {
+                memset(rowbuf + j * 5, *(data + i*SCREENWIDTH + j), 5);
+            }
+
+            // write the row 6 times
+            for (j = 0; j < 6; j++)
+            {
+                png_write_row(ppng, rowbuf);
+            }
+        }
+
+        free(rowbuf);
+    }
+
+    png_write_end(ppng, pinfo);
+    png_destroy_write_struct(&ppng, &pinfo);
+    fclose(handle);
+}
+#endif
+
 //
 // V_ScreenShot
 //
@@ -713,12 +820,14 @@ void V_ScreenShot(char *format)

     // find a file name to save it to

+#ifdef HAVE_LIBPNG
     extern int png_screenshots;
     if (png_screenshots)
     {
         ext = "png";
     }
     else
+#endif
     {
         ext = "pcx";
     }
@@ -738,11 +847,15 @@ void V_ScreenShot(char *format)
         I_Error ("V_ScreenShot: Couldn't create a PCX");
     }

+#ifdef HAVE_LIBPNG
     if (png_screenshots)
     {
-        I_SavePNGScreenshot(lbmname);
+    WritePNGfile(lbmname, I_VideoBuffer,
+                 SCREENWIDTH, SCREENHEIGHT,
+                 W_CacheLumpName (DEH_String("PLAYPAL"), PU_CACHE));
     }
     else
+#endif
     {
     // save the pcx file
     WritePCXfile(lbmname, I_VideoBuffer,