SCR_ScreenShot_f: change default format to png, using stb_image_write

Add optional format and quality args to "screenshot" command,
can specify tga, png, jpg

git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@1465 af15c1b1-3010-417e-b628-4374ebc0bcbd
This commit is contained in:
Eric Wasylishen 2017-08-08 05:07:56 +00:00
parent 10ed2c85dc
commit 4a02827fe6
4 changed files with 1604 additions and 7 deletions

View file

@ -757,6 +757,14 @@ SCREEN SHOTS
==============================================================================
*/
static void SCR_ScreenShot_Usage (void)
{
Con_Printf ("usage: screenshot <format> <quality>\n");
Con_Printf (" format must be \"png\" or \"tga\" or \"jpg\"\n");
Con_Printf (" quality must be 1-100\n");
return;
}
/*
==================
SCR_ScreenShot_f -- johnfitz -- rewritten to use Image_WriteTGA
@ -765,15 +773,44 @@ SCR_ScreenShot_f -- johnfitz -- rewritten to use Image_WriteTGA
void SCR_ScreenShot_f (void)
{
byte *buffer;
char tganame[16]; //johnfitz -- was [80]
char ext[4];
char imagename[16]; //johnfitz -- was [80]
char checkname[MAX_OSPATH];
int i;
int i, quality;
qboolean ok;
Q_strncpy (ext, "png", sizeof(ext));
if (Cmd_Argc () >= 2)
{
const char *requested_ext = Cmd_Argv (1);
if (!q_strcasecmp ("png", requested_ext)
|| !q_strcasecmp ("tga", requested_ext)
|| !q_strcasecmp ("jpg", requested_ext))
Q_strncpy (ext, requested_ext, sizeof(ext));
else
{
SCR_ScreenShot_Usage ();
return;
}
}
// read quality as the 3rd param (only used for JPG)
quality = 90;
if (Cmd_Argc () >= 3)
quality = Q_atoi (Cmd_Argv(2));
if (quality < 1 || quality > 100)
{
SCR_ScreenShot_Usage ();
return;
}
// find a file name to save it to
for (i=0; i<10000; i++)
{
q_snprintf (tganame, sizeof(tganame), "spasm%04i.tga", i); // "fitz%04i.tga"
q_snprintf (checkname, sizeof(checkname), "%s/%s", com_gamedir, tganame);
q_snprintf (imagename, sizeof(imagename), "spasm%04i.%s", i, ext); // "fitz%04i.tga"
q_snprintf (checkname, sizeof(checkname), "%s/%s", com_gamedir, imagename);
if (Sys_FileTime(checkname) == -1)
break; // file doesn't exist
}
@ -794,10 +831,19 @@ void SCR_ScreenShot_f (void)
glReadPixels (glx, gly, glwidth, glheight, GL_RGB, GL_UNSIGNED_BYTE, buffer);
// now write the file
if (Image_WriteTGA (tganame, buffer, glwidth, glheight, 24, false))
Con_Printf ("Wrote %s\n", tganame);
if (!q_strncasecmp (ext, "png", sizeof(ext)))
ok = Image_WritePNG (imagename, buffer, glwidth, glheight, 24, false);
else if (!q_strncasecmp (ext, "tga", sizeof(ext)))
ok = Image_WriteTGA (imagename, buffer, glwidth, glheight, 24, false);
else if (!q_strncasecmp (ext, "jpg", sizeof(ext)))
ok = Image_WriteJPG (imagename, buffer, glwidth, glheight, 24, quality, false);
else
Con_Printf ("SCR_ScreenShot_f: Couldn't create a TGA file\n");
ok = false;
if (ok)
Con_Printf ("Wrote %s\n", imagename);
else
Con_Printf ("SCR_ScreenShot_f: Couldn't create %s\n", imagename);
free (buffer);
}

View file

@ -23,6 +23,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "quakedef.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
static char loadfilename[MAX_OSPATH]; //file scope so that error messages can use it
typedef struct stdio_buffer_s {
@ -467,3 +470,91 @@ byte *Image_LoadPCX (FILE *f, int *width, int *height)
*height = h;
return data;
}
//==============================================================================
//
// STB_IMAGE_WRITE
//
//==============================================================================
static byte *CopyFlipped(byte *data, int width, int height, int bpp)
{
int y, rowsize;
byte *flipped;
rowsize = width * (bpp / 8);
flipped = (byte *) malloc(height * rowsize);
if (!flipped)
return NULL;
for (y=0; y<height; y++)
{
memcpy(&flipped[y * rowsize], &data[(height - 1 - y) * rowsize], rowsize);
}
return flipped;
}
typedef enum {
format_png,
format_jpg
} imageformat_t;
/*
============
Image_WriteSTB -- writes using stb_image_write
returns true if successful
============
*/
static qboolean
Image_WriteSTB (const char *name, byte *data, int width, int height, int bpp, imageformat_t format, int quality, qboolean upsidedown)
{
unsigned error;
char pathname[MAX_OSPATH];
byte *flipped;
int bytes_per_pixel;
if (!(bpp == 32 || bpp == 24))
Sys_Error ("bpp not 24 or 32");
bytes_per_pixel = bpp / 8;
Sys_mkdir (com_gamedir); //if we've switched to a nonexistant gamedir, create it now so we don't crash
q_snprintf (pathname, sizeof(pathname), "%s/%s", com_gamedir, name);
if (!upsidedown)
{
flipped = CopyFlipped (data, width, height, bpp);
if (!flipped)
return false;
}
else
flipped = data;
switch (format)
{
case format_png:
error = stbi_write_png (pathname, width, height, bytes_per_pixel, flipped, width * bytes_per_pixel);
break;
case format_jpg:
error = stbi_write_jpg (pathname, width, height, bytes_per_pixel, flipped, quality);
break;
default:
Sys_Error ("invalid format");
}
if (!upsidedown)
free (flipped);
return (error != 0);
}
qboolean Image_WritePNG (const char *name, byte *data, int width, int height, int bpp, qboolean upsidedown)
{
return Image_WriteSTB (name, data, width, height, bpp, format_png, 0, upsidedown);
}
qboolean Image_WriteJPG (const char *name, byte *data, int width, int height, int bpp, int quality, qboolean upsidedown)
{
return Image_WriteSTB (name, data, width, height, bpp, format_jpg, quality, upsidedown);
}

View file

@ -31,6 +31,8 @@ byte *Image_LoadPCX (FILE *f, int *width, int *height);
byte *Image_LoadImage (const char *name, int *width, int *height);
qboolean Image_WriteTGA (const char *name, byte *data, int width, int height, int bpp, qboolean upsidedown);
qboolean Image_WritePNG (const char *name, byte *data, int width, int height, int bpp, qboolean upsidedown);
qboolean Image_WriteJPG (const char *name, byte *data, int width, int height, int bpp, int quality, qboolean upsidedown);
#endif /* __GL_IMAGE_H */

1458
Quake/stb_image_write.h Normal file

File diff suppressed because it is too large Load diff