shithub: choc

Download patch

ref: 7215d13b6c4f253b6d1752a0fa2d0b9a0d16fc1f
parent: ca0e7776d0048f635d68e3b05313c7bc7898ab3b
author: Jonathan Dowland <jon+github@alcopop.org>
date: Thu Jul 14 19:44:16 EDT 2016

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

--- a/configure.ac
+++ b/configure.ac
@@ -37,7 +37,6 @@
 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 @@
     ])
 ])
 
+# 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])
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -21,8 +21,7 @@
 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 @@
                @LDFLAGS@                                   \
                @SDL_LIBS@                                  \
                @SDLMIXER_LIBS@                             \
-               @SDLNET_LIBS@                               \
-               @SDLIMAGE_LIBS@
+               @SDLNET_LIBS@
 
 if HAVE_WINDRES
 @PROGRAM_PREFIX@doom_SOURCES=$(SOURCE_FILES_WITH_DEH) resource.rc
--- 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
@@ -1283,28 +1282,4 @@
     M_BindStringVariable("window_position",        &window_position);
     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);
-    }
 }
--- a/src/i_video.h
+++ b/src/i_video.h
@@ -78,8 +78,6 @@
 
 void I_EnableLoadingDisk(int xoffs, int yoffs);
 
-void I_SavePNGScreenshot (char *filename);
-
 extern char *video_driver;
 extern boolean screenvisible;
 
--- a/src/setup/display.c
+++ b/src/setup/display.c
@@ -200,8 +200,10 @@
             || 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);
--- 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,7 +704,111 @@
     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,6 +820,7 @@
     
     // find a file name to save it to
 
+#ifdef HAVE_LIBPNG
     extern int png_screenshots;
     if (png_screenshots)
     {
@@ -719,6 +827,7 @@
         ext = "png";
     }
     else
+#endif
     {
         ext = "pcx";
     }
@@ -738,11 +847,15 @@
         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,