dynamically load SDL_Image at runtime for PNG screenshots

Fixes #31
This commit is contained in:
Fabian Greffrath 2020-01-13 12:03:15 +01:00
parent 37767f4858
commit 3cd2ffdde5
10 changed files with 211 additions and 40 deletions

View File

@ -26,6 +26,7 @@ winmbf_SOURCES = \
hu_stuff.c hu_stuff.h \
i_main.c \
i_net.c i_net.h \
i_savepng.c i_savepng.h \
i_sound.c i_sound.h \
i_system.c i_system.h \
i_video.c i_video.h \
@ -80,5 +81,5 @@ winmbf_SOURCES = \
w_wad.c w_wad.h \
wi_stuff.c wi_stuff.h \
z_zone.c z_zone.h
winmbf_CFLAGS = @SDL_CFLAGS@ @SDL_image_CFLAGS@ @SDL_mixer_CFLAGS@ @SDL_net_CFLAGS@
winmbf_LDADD = @SDL_LIBS@ @SDL_image_LIBS@ @SDL_mixer_LIBS@ @SDL_net_LIBS@
winmbf_CFLAGS = @SDL_CFLAGS@ @SDL_mixer_CFLAGS@ @SDL_net_CFLAGS@
winmbf_LDADD = @SDL_LIBS@ @SDL_mixer_LIBS@ @SDL_net_LIBS@

View File

@ -31,13 +31,12 @@
#include "d_io.h" // haleyjd
#include "SDL_filesystem.h" // [FG] SDL_GetPrefPath()
#include "SDL_stdinc.h" // [FG] SDL_qsort()
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "SDL_stdinc.h" // [FG] SDL_qsort()
#include "doomdef.h"
#include "doomstat.h"
#include "dstrings.h"
@ -52,6 +51,7 @@
#include "m_misc.h"
#include "m_misc2.h" // [FG] M_StringDuplicate()
#include "m_menu.h"
#include "i_savepng.h" // [FG] SavePNG
#include "i_system.h"
#include "i_sound.h"
#include "i_video.h"
@ -1372,6 +1372,9 @@ void D_DoomMain(void)
int p, slot;
char file[PATH_MAX+1]; // killough 3/22/98
// [FG] save screenshots in PNG format
I_InitSavePNG();
setbuf(stdout,NULL);
#if defined(_WIN32)

84
Source/i_savepng.c Normal file
View File

@ -0,0 +1,84 @@
//
// Copyright(C) 2020 Fabian Greffrath
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//
// DESCRIPTION:
// Dynamically load SDL2_Image for PNG screenshots.
//
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_DLOPEN
#include <dlfcn.h>
#elif _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#include "doomtype.h"
#include "i_savepng.h"
savepng_t SavePNG = NULL;
static const char *sdl2_image_libs[] = {
#ifdef HAVE_DLOPEN
"libSDL2_image-2.0.so.0",
"libSDL2_image-2.0.so",
"libSDL2_image.so",
#elif _WIN32
"SDL2_image.dll",
#endif
};
void I_InitSavePNG (void)
{
int i;
#ifdef HAVE_DLOPEN
void *sdl2_image_lib = NULL;
void *savepng_func = NULL;
#elif _WIN32
HMODULE sdl2_image_lib = NULL;
FARPROC savepng_func = NULL;
#endif
for (i = 0; i < arrlen(sdl2_image_libs); i++)
{
#ifdef HAVE_DLOPEN
sdl2_image_lib = dlopen(sdl2_image_libs[i], RTLD_LAZY);
#elif _WIN32
sdl2_image_lib = LoadLibrary(TEXT(sdl2_image_libs[i]));
#endif
if (sdl2_image_lib != NULL)
{
break;
}
}
if (sdl2_image_lib != NULL)
{
#ifdef HAVE_DLOPEN
savepng_func = dlsym(sdl2_image_lib, "IMG_SavePNG");
#elif _WIN32
savepng_func = GetProcAddress(sdl2_image_lib, "IMG_SavePNG");
#endif
}
SavePNG = (savepng_t) savepng_func;
}

32
Source/i_savepng.h Normal file
View File

@ -0,0 +1,32 @@
//
// Copyright(C) 2020 Fabian Greffrath
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//
// DESCRIPTION:
// Dynamically load SDL2_Image for PNG screenshots.
//
#ifndef __I_SAVEPNG__
#define __I_SAVEPNG__
typedef int (*savepng_t)(void *, const char *);
extern savepng_t SavePNG;
extern void I_InitSavePNG (void);
#endif

View File

@ -28,11 +28,6 @@
#include "SDL.h" // haleyjd
#include "config.h"
#ifdef HAVE_SDL_IMAGE
#include "SDL_image.h"
#endif
#include "z_zone.h" /* memory allocation wrappers -- killough */
#include "doomstat.h"
#include "v_video.h"
@ -46,6 +41,7 @@
#include "m_menu.h"
#include "wi_stuff.h"
#include "i_video.h"
#include "i_savepng.h" // [FG] SavePNG()
SDL_Surface *sdlscreen;
@ -840,13 +836,13 @@ void I_ShutdownGraphics(void)
}
}
// [FG] save screenshots in PNG format
boolean I_WritePNGfile(char *filename)
{
#ifdef HAVE_SDL_IMAGE
return IMG_SavePNG(sdlscreen, filename) == 0;
#else
return false;
#endif
if (SavePNG)
return SavePNG(sdlscreen, filename) == 0;
else
return false;
}
extern boolean setsizeneeded;

View File

@ -49,6 +49,8 @@
#include "m_menu.h"
#include "d_deh.h"
#include "m_misc.h"
#include "m_misc2.h" // [FG] M_StringDuplicate()
#include "i_savepng.h" // [FG] SavePNG()
extern patch_t* hu_font[HU_FONTSIZE];
extern boolean message_dontfuckwithme;
@ -2995,11 +2997,7 @@ setup_menu_t gen_settings1[] = { // General Settings screen1
{"Translucency filter percentage", S_NUM, m_null, G_X,
G_Y + general_transpct*8, {"tran_filter_pct"}, 0, 0, M_Trans},
#ifdef HAVE_SDL_IMAGE
{"PCX instead of PNG for screenshots", S_YESNO, m_null, G_X,
#else
{"PCX instead of BMP for screenshots", S_YESNO, m_null, G_X,
#endif
G_Y + general_pcx*8, {"screenshot_pcx"}},
{"Flash Icon During Disk IO", S_YESNO, m_null, G_X,
@ -5621,6 +5619,16 @@ void M_Init(void)
{
strcpy(OptionsMenu[scrnsize].name, "M_DISP");
}
// [FG] save screenshots in PNG format
if (SavePNG)
{
const char *bmp_text, *png_text;
bmp_text = gen_settings1[general_pcx+1].m_text;
png_text = M_StringReplace(bmp_text, "BMP", "PNG");
gen_settings1[general_pcx+1].m_text = png_text;
}
}
// killough 10/98: allow runtime changing of menu order

View File

@ -46,6 +46,7 @@
#include "s_sound.h"
#include "sounds.h"
#include "d_main.h"
#include "i_savepng.h" // [FG] SavePNG()
#include "d_io.h"
#include <errno.h>
@ -1054,11 +1055,7 @@ default_t defaults[] = {
"screenshot_pcx",
&screenshot_pcx, NULL,
{1}, {0,1}, number, ss_gen, wad_no,
#ifdef HAVE_SDL_IMAGE
"1 to take a screenshot in PCX format, 0 for PNG"
#else
"1 to take a screenshot in PCX format, 0 for BMP"
#endif
"1 to take a screenshot in PCX format, 0 for BMP (or PNG)"
},
{
@ -2429,6 +2426,7 @@ boolean WriteBMPfile(char *filename, byte *data, int width,
return I_EndRead(), true; // killough 10/98
}
// [FG] save screenshots in PNG format
boolean WritePNGfile(char *filename, byte *data, int width,
int height, byte *palette)
{
@ -2457,11 +2455,7 @@ void M_ScreenShot (void)
do
sprintf(lbmname, //jff 3/30/98 pcx or bmp?
#ifdef HAVE_SDL_IMAGE
screenshot_pcx ? "doom%02d.pcx" : "doom%02d.png", shot++);
#else
screenshot_pcx ? "doom%02d.pcx" : "doom%02d.bmp", shot++);
#endif
screenshot_pcx ? "doom%02d.pcx" : (SavePNG ? "doom%02d.png" : "doom%02d.bmp"), shot++);
while (!access(lbmname,0) && --tries);
if (tries)
@ -2479,11 +2473,7 @@ void M_ScreenShot (void)
// killough 10/98: detect failure and remove file if error
// killough 11/98: add hires support
#ifdef HAVE_SDL_IMAGE
if (!(success = (screenshot_pcx ? WritePCXfile : WritePNGfile)
#else
if (!(success = (screenshot_pcx ? WritePCXfile : WriteBMPfile)
#endif
if (!(success = (screenshot_pcx ? WritePCXfile : (SavePNG ? WritePNGfile : WriteBMPfile))
(lbmname,linear, SCREENWIDTH<<hires, SCREENHEIGHT<<hires,pal)))
{
int t = errno;

View File

@ -121,6 +121,67 @@ char *M_StringDuplicate(const char *orig)
return result;
}
// String replace function.
char *M_StringReplace(const char *haystack, const char *needle,
const char *replacement)
{
char *result, *dst;
const char *p;
size_t needle_len = strlen(needle);
size_t result_len, dst_len;
// Iterate through occurrences of 'needle' and calculate the size of
// the new string.
result_len = strlen(haystack) + 1;
p = haystack;
for (;;)
{
p = strstr(p, needle);
if (p == NULL)
{
break;
}
p += needle_len;
result_len += strlen(replacement) - needle_len;
}
// Construct new string.
result = malloc(result_len);
if (result == NULL)
{
I_Error("M_StringReplace: Failed to allocate new string");
return NULL;
}
dst = result; dst_len = result_len;
p = haystack;
while (*p != '\0')
{
if (!strncmp(p, needle, needle_len))
{
M_StringCopy(dst, replacement, dst_len);
p += needle_len;
dst += strlen(replacement);
dst_len -= strlen(replacement);
}
else
{
*dst = *p;
++dst; --dst_len;
++p;
}
}
*dst = '\0';
return result;
}
// Safe string copy function that works like OpenBSD's strlcpy().
// Returns true if the string was not truncated.

View File

@ -28,6 +28,8 @@ void M_ForceLowercase(char *text);
char *M_StringDuplicate(const char *orig);
boolean M_StringCopy(char *dest, const char *src, size_t dest_size);
boolean M_StringConcat(char *dest, const char *src, size_t dest_size);
char *M_StringReplace(const char *haystack, const char *needle,
const char *replacement);
char *M_StringJoin(const char *s, ...);
boolean M_StringEndsWith(const char *s, const char *suffix);

View File

@ -18,18 +18,12 @@ fi
# Checks for libraries.
AC_SEARCH_LIBS([pow], [m])
AC_SEARCH_LIBS([dlopen], [dl dld])
PKG_CHECK_MODULES([SDL], [sdl2])
PKG_CHECK_MODULES([SDL_mixer], [SDL2_mixer])
PKG_CHECK_MODULES([SDL_net], [SDL2_net])
AC_DEFINE([MY_SDL_VER], [1], [This is WinMBF])
AC_ARG_WITH([sdlimage], AS_HELP_STRING([--with-sdlimage], [Build with SDL2_Image for PNG screenshots]))
AS_IF([test "x$with_sdlimage" = "xyes"],
[PKG_CHECK_MODULES([SDL_image], [SDL2_image],
[AC_DEFINE([HAVE_SDL_IMAGE], [1], [PNG screenshots])]
)]
)
# Checks for header files.
AC_CHECK_HEADERS([fcntl.h limits.h malloc.h stddef.h stdint.h stdlib.h string.h unistd.h])