renders: reuse VID_ImageDecode

This commit is contained in:
Denis Pauk 2024-06-21 00:58:18 +03:00
parent 9f84e40ab7
commit 1ce49294e7
5 changed files with 138 additions and 270 deletions

View file

@ -26,108 +26,11 @@
#include "../ref_shared.h"
// Fix Jennell Jaquays' name in the Quitscreen
// this is 98x11 pixels, each value an index
// into the standard baseq2/pak0/pics/quit.pcx colormap
static unsigned char quitscreenfix[] = {
191,191,191,47,28,39,4,4,39,1,47,28,47,28,29,1,
28,28,47,31,31,1,29,31,1,28,47,47,47,47,29,28,
47,31,30,28,40,40,4,28,28,40,39,40,29,102,102,245,
28,39,4,4,39,103,40,40,1,1,102,94,47,47,1,94,
94,94,94,47,102,245,103,103,103,47,1,102,1,102,29,29,
29,29,47,28,245,31,31,31,47,1,28,1,28,47,1,102, 102,102,
191,191,142,47,4,8,8,8,8,4,47,28,1,28,29,28,
29,29,31,1,47,245,47,47,28,28,31,47,28,1,31,1,
1,245,47,39,8,8,8,40,39,8,8,8,39,1,1,47,
4,8,8,8,8,4,47,29,28,31,28,28,29,28,28,28,
29,28,31,28,47,29,1,28,31,47,1,28,1,1,29,29,
29,47,28,1,28,28,245,28,28,28,28,47,29,28,47,102,102,103,
191,191,142,31,29,36,8,8,36,31,40,39,40,4,1,1,
39,40,39,40,40,31,28,40,40,4,39,40,28,47,31,40,
39,40,4,1,36,8,8,4,47,36,8,8,39,1,1,1,
29,36,8,8,36,4,4,39,40,4,47,1,47,40,40,39,
39,40,28,40,40,47,45,39,40,28,4,39,40,4,39,1,
28,4,40,28,28,4,39,28,47,40,40,39,40,39,28,28,1,103,
1,142,29,142,28,39,8,8,36,36,8,8,8,8,36,1,
8,8,8,8,8,36,39,8,8,8,8,8,36,40,36,8,
8,8,8,36,40,8,8,40,1,4,8,8,40,1,1,31,
28,39,8,8,36,8,8,8,8,8,36,31,36,8,8,8,
8,8,36,8,8,4,40,8,8,36,8,8,8,8,8,36,
40,8,8,40,39,8,8,40,36,8,8,8,8,8,39,29,28,29,
103,191,142,47,28,40,8,8,40,8,8,33,33,8,8,36,
8,8,36,36,8,8,36,8,8,36,36,8,8,36,8,8,
33,33,8,8,36,8,8,4,47,40,8,8,39,47,28,245,
28,40,8,8,40,40,36,36,33,8,8,36,8,8,36,36,
8,8,36,8,8,40,40,8,8,40,4,36,36,33,8,8,
36,8,8,39,39,8,8,36,8,8,33,36,36,39,28,1,47,28,
103,246,1,47,1,39,8,8,40,8,8,8,8,8,8,36,
8,8,4,40,8,8,36,8,8,40,4,8,8,36,8,8,
8,8,8,8,36,8,8,40,29,39,8,8,39,1,1,47,
1,39,8,8,40,36,8,8,8,8,8,36,8,8,4,40,
8,8,36,8,8,40,39,8,8,40,36,8,8,8,8,8,
36,8,8,39,40,8,8,40,36,8,8,8,8,36,28,1,1,29,
103,47,40,40,4,36,8,8,36,8,8,33,36,36,36,4,
8,8,39,4,8,8,36,8,8,4,40,8,8,36,8,8,
33,36,36,36,36,8,8,40,31,40,8,8,40,47,40,40,
4,36,8,8,36,8,8,33,33,8,8,36,8,8,36,36,
8,8,36,8,8,36,36,8,8,36,8,8,33,33,8,8,
36,8,8,36,36,8,8,4,39,36,36,33,8,8,4,40,4,31,
191,40,8,8,8,8,8,36,29,36,8,8,8,8,8,40,
8,8,40,4,8,8,36,8,8,40,39,8,8,39,36,8,
8,8,8,8,39,8,8,39,45,4,8,8,40,40,8,8,
8,8,8,36,29,36,8,8,8,8,8,40,36,8,8,8,
8,8,40,36,8,8,8,8,8,40,36,8,8,8,8,8,
40,36,8,8,8,8,8,36,8,8,8,8,8,36,4,8,8,4,
47,45,40,39,40,39,39,245,246,1,40,40,40,39,4,47,
40,4,28,29,39,40,30,39,39,1,28,40,4,28,1,40,
40,40,39,4,29,40,39,1,1,1,4,4,47,45,40,39,
40,39,39,245,246,29,39,40,40,40,4,47,28,39,39,36,
8,8,4,1,39,40,4,40,40,1,29,4,39,4,40,39,
1,39,36,36,33,8,8,4,39,4,39,4,40,47,36,8,8,40,
1,28,47,28,28,29,1,28,47,28,31,28,28,27,47,28,
45,246,30,28,245,29,47,47,29,30,28,47,27,1,246,47,
47,47,1,28,47,28,47,1,47,47,1,29,29,47,47,28,
28,29,1,47,1,47,47,28,31,47,47,31,47,47,47,4,
8,8,39,245,1,47,28,245,28,47,31,28,47,28,28,28,
40,8,8,8,8,8,36,47,28,1,246,47,1,40,8,8,36,1,
47,1,102,1,102,102,47,94,94,102,47,47,102,102,102,102,
94,1,94,47,102,1,102,47,30,30,102,27,47,102,94,1,
102,47,1,94,102,103,1,102,103,103,47,47,47,29,1,29,
28,28,29,28,1,47,28,31,29,1,47,29,28,1,1,47,
4,39,1,47,47,1,28,28,28,47,1,28,45,28,47,47,
1,40,4,4,40,4,29,28,31,45,47,28,47,47,4,40,28,28
};
static void
fixQuitScreen(byte* px)
{
// overwrite 11 lines, 98 pixels each, from quitscreenfix[]
// starting at line 140, column 188
// quitscreen is 320x240 px
int r, qsIdx = 0;
px += 140*320; // go to line 140
px += 188; // to colum 188
for(r=0; r<11; ++r)
{
memcpy(px, quitscreenfix+qsIdx, 98);
qsIdx += 98;
px += 320;
}
}
void
LoadPCX(const char *origname, byte **pic, byte **palette, int *width, int *height)
{
byte *raw;
pcx_t *pcx;
int x, y;
int len, full_size;
int pcx_width, pcx_height;
qboolean image_issues = false;
int dataByte, runLength;
byte *out, *pix;
char filename[256];
int bytesPerPixel;
FixFileExt(origname, "pcx", filename, sizeof(filename));
@ -138,152 +41,12 @@ LoadPCX(const char *origname, byte **pic, byte **palette, int *width, int *heigh
*palette = NULL;
}
/* load the file */
len = ri.FS_LoadFile(filename, (void **)&raw);
ri.VID_ImageDecode(filename, pic, palette, width, height, &bytesPerPixel);
if (!raw || len < sizeof(pcx_t))
if (!(*pic))
{
R_Printf(PRINT_DEVELOPER, "Bad pcx file %s, length %d\n", filename, len);
return;
R_Printf(PRINT_DEVELOPER, "Bad pcx file %s\n", filename);
}
/* parse the PCX file */
pcx = (pcx_t *)raw;
pcx->xmin = LittleShort(pcx->xmin);
pcx->ymin = LittleShort(pcx->ymin);
pcx->xmax = LittleShort(pcx->xmax);
pcx->ymax = LittleShort(pcx->ymax);
pcx->hres = LittleShort(pcx->hres);
pcx->vres = LittleShort(pcx->vres);
pcx->bytes_per_line = LittleShort(pcx->bytes_per_line);
pcx->palette_type = LittleShort(pcx->palette_type);
raw = &pcx->data;
pcx_width = pcx->xmax - pcx->xmin;
pcx_height = pcx->ymax - pcx->ymin;
if ((pcx->manufacturer != 0x0a) || (pcx->version != 5) ||
(pcx->encoding != 1) || (pcx->bits_per_pixel != 8) ||
(pcx_width >= 4096) || (pcx_height >= 4096))
{
R_Printf(PRINT_ALL, "Bad pcx file %s\n", filename);
ri.FS_FreeFile(pcx);
return;
}
full_size = (pcx_height + 1) * (pcx_width + 1);
out = malloc(full_size);
if (!out)
{
R_Printf(PRINT_ALL, "Can't allocate\n");
ri.FS_FreeFile(pcx);
return;
}
*pic = out;
pix = out;
if (palette)
{
*palette = malloc(768);
if (!(*palette))
{
R_Printf(PRINT_ALL, "Can't allocate\n");
free(out);
ri.FS_FreeFile(pcx);
return;
}
if (len > 768)
{
memcpy(*palette, (byte *)pcx + len - 768, 768);
}
else
{
image_issues = true;
}
}
if (width)
{
*width = pcx_width + 1;
}
if (height)
{
*height = pcx_height + 1;
}
for (y = 0; y <= pcx_height; y++, pix += pcx_width + 1)
{
for (x = 0; x <= pcx_width; )
{
if (raw - (byte *)pcx > len)
{
// no place for read
image_issues = true;
x = pcx_width;
break;
}
dataByte = *raw++;
if ((dataByte & 0xC0) == 0xC0)
{
runLength = dataByte & 0x3F;
if (raw - (byte *)pcx > len)
{
// no place for read
image_issues = true;
x = pcx_width;
break;
}
dataByte = *raw++;
}
else
{
runLength = 1;
}
while (runLength-- > 0)
{
if ((*pic + full_size) <= (pix + x))
{
// no place for write
image_issues = true;
x += runLength;
runLength = 0;
}
else
{
pix[x++] = dataByte;
}
}
}
}
if (raw - (byte *)pcx > len)
{
R_Printf(PRINT_DEVELOPER, "PCX file %s was malformed", filename);
free(*pic);
*pic = NULL;
}
else if(pcx_width == 319 && pcx_height == 239
&& Q_strcasecmp(filename, "pics/quit.pcx") == 0
&& Com_BlockChecksum(pcx, len) == 3329419434u)
{
// it's the quit screen, and the baseq2 one (identified by checksum)
// so fix it
fixQuitScreen(*pic);
}
if (image_issues)
{
R_Printf(PRINT_ALL, "PCX file %s has possible size issues.\n", filename);
}
ri.FS_FreeFile(pcx);
}
void

View file

@ -30,19 +30,6 @@
#include "../ref_shared.h"
// don't need HDR stuff
#define STBI_NO_LINEAR
#define STBI_NO_HDR
// make sure STB_image uses standard malloc(), as we'll use standard free() to deallocate
#define STBI_MALLOC(sz) malloc(sz)
#define STBI_REALLOC(p,sz) realloc(p,sz)
#define STBI_FREE(p) free(p)
// Switch of the thread local stuff. Breaks mingw under Windows.
#define STBI_NO_THREAD_LOCALS
// include implementation part of stb_image into this file
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
// include resize implementation
#define STB_IMAGE_RESIZE_IMPLEMENTATION
#include "stb_image_resize.h"
@ -71,31 +58,29 @@ FixFileExt(const char *origname, const char *ext, char *filename, size_t size)
qboolean
LoadSTB(const char *origname, const char* type, byte **pic, int *width, int *height)
{
int w, h, bytesPerPixel;
char filename[256];
byte* data = NULL;
FixFileExt(origname, type, filename, sizeof(filename));
*pic = NULL;
byte* rawdata = NULL;
int rawsize = ri.FS_LoadFile(filename, (void **)&rawdata);
if (rawdata == NULL)
{
return false;
}
int w, h, bytesPerPixel;
byte* data = NULL;
data = stbi_load_from_memory(rawdata, rawsize, &w, &h, &bytesPerPixel, STBI_rgb_alpha);
ri.VID_ImageDecode(filename, &data, NULL, &w, &h, &bytesPerPixel);
if (data == NULL)
{
R_Printf(PRINT_ALL, "%s couldn't load data from %s: %s!\n",
__func__, filename, stbi_failure_reason());
ri.FS_FreeFile(rawdata);
return false;
}
ri.FS_FreeFile(rawdata);
if (bytesPerPixel != 4)
{
free(data);
R_Printf(PRINT_ALL, "%s unexpected file format of %s with %d bytes per pixel!\n",
__func__, filename, bytesPerPixel);
return false;
}
R_Printf(PRINT_DEVELOPER, "%s() loaded: %s\n", __func__, filename);

View file

@ -253,6 +253,9 @@ typedef struct
// called with image data of width*height pixel which comp bytes per pixel (must be 3 or 4 for RGB or RGBA)
// expects the pixels data to be row-wise, starting at top left
void (IMPORT *Vid_WriteScreenshot)( int width, int height, int comp, const void* data );
/* load image from file */
void (IMPORT *VID_ImageDecode)( const char *filename, byte **pic, byte **palette,
int *width, int *height, int *bytesPerPixel);
qboolean (IMPORT *GLimp_InitGraphics)(int fullscreen, int *pwidth, int *pheight);
qboolean (IMPORT *GLimp_GetDesktopMode)(int *pwidth, int *pheight);

View file

@ -40,6 +40,96 @@
#define STB_IMAGE_IMPLEMENTATION
#include "../refresh/files/stb_image.h"
// Fix Jennell Jaquays' name in the Quitscreen
// this is 98x11 pixels, each value an index
// into the standard baseq2/pak0/pics/quit.pcx colormap
static unsigned char quitscreenfix[] = {
191,191,191,47,28,39,4,4,39,1,47,28,47,28,29,1,
28,28,47,31,31,1,29,31,1,28,47,47,47,47,29,28,
47,31,30,28,40,40,4,28,28,40,39,40,29,102,102,245,
28,39,4,4,39,103,40,40,1,1,102,94,47,47,1,94,
94,94,94,47,102,245,103,103,103,47,1,102,1,102,29,29,
29,29,47,28,245,31,31,31,47,1,28,1,28,47,1,102, 102,102,
191,191,142,47,4,8,8,8,8,4,47,28,1,28,29,28,
29,29,31,1,47,245,47,47,28,28,31,47,28,1,31,1,
1,245,47,39,8,8,8,40,39,8,8,8,39,1,1,47,
4,8,8,8,8,4,47,29,28,31,28,28,29,28,28,28,
29,28,31,28,47,29,1,28,31,47,1,28,1,1,29,29,
29,47,28,1,28,28,245,28,28,28,28,47,29,28,47,102,102,103,
191,191,142,31,29,36,8,8,36,31,40,39,40,4,1,1,
39,40,39,40,40,31,28,40,40,4,39,40,28,47,31,40,
39,40,4,1,36,8,8,4,47,36,8,8,39,1,1,1,
29,36,8,8,36,4,4,39,40,4,47,1,47,40,40,39,
39,40,28,40,40,47,45,39,40,28,4,39,40,4,39,1,
28,4,40,28,28,4,39,28,47,40,40,39,40,39,28,28,1,103,
1,142,29,142,28,39,8,8,36,36,8,8,8,8,36,1,
8,8,8,8,8,36,39,8,8,8,8,8,36,40,36,8,
8,8,8,36,40,8,8,40,1,4,8,8,40,1,1,31,
28,39,8,8,36,8,8,8,8,8,36,31,36,8,8,8,
8,8,36,8,8,4,40,8,8,36,8,8,8,8,8,36,
40,8,8,40,39,8,8,40,36,8,8,8,8,8,39,29,28,29,
103,191,142,47,28,40,8,8,40,8,8,33,33,8,8,36,
8,8,36,36,8,8,36,8,8,36,36,8,8,36,8,8,
33,33,8,8,36,8,8,4,47,40,8,8,39,47,28,245,
28,40,8,8,40,40,36,36,33,8,8,36,8,8,36,36,
8,8,36,8,8,40,40,8,8,40,4,36,36,33,8,8,
36,8,8,39,39,8,8,36,8,8,33,36,36,39,28,1,47,28,
103,246,1,47,1,39,8,8,40,8,8,8,8,8,8,36,
8,8,4,40,8,8,36,8,8,40,4,8,8,36,8,8,
8,8,8,8,36,8,8,40,29,39,8,8,39,1,1,47,
1,39,8,8,40,36,8,8,8,8,8,36,8,8,4,40,
8,8,36,8,8,40,39,8,8,40,36,8,8,8,8,8,
36,8,8,39,40,8,8,40,36,8,8,8,8,36,28,1,1,29,
103,47,40,40,4,36,8,8,36,8,8,33,36,36,36,4,
8,8,39,4,8,8,36,8,8,4,40,8,8,36,8,8,
33,36,36,36,36,8,8,40,31,40,8,8,40,47,40,40,
4,36,8,8,36,8,8,33,33,8,8,36,8,8,36,36,
8,8,36,8,8,36,36,8,8,36,8,8,33,33,8,8,
36,8,8,36,36,8,8,4,39,36,36,33,8,8,4,40,4,31,
191,40,8,8,8,8,8,36,29,36,8,8,8,8,8,40,
8,8,40,4,8,8,36,8,8,40,39,8,8,39,36,8,
8,8,8,8,39,8,8,39,45,4,8,8,40,40,8,8,
8,8,8,36,29,36,8,8,8,8,8,40,36,8,8,8,
8,8,40,36,8,8,8,8,8,40,36,8,8,8,8,8,
40,36,8,8,8,8,8,36,8,8,8,8,8,36,4,8,8,4,
47,45,40,39,40,39,39,245,246,1,40,40,40,39,4,47,
40,4,28,29,39,40,30,39,39,1,28,40,4,28,1,40,
40,40,39,4,29,40,39,1,1,1,4,4,47,45,40,39,
40,39,39,245,246,29,39,40,40,40,4,47,28,39,39,36,
8,8,4,1,39,40,4,40,40,1,29,4,39,4,40,39,
1,39,36,36,33,8,8,4,39,4,39,4,40,47,36,8,8,40,
1,28,47,28,28,29,1,28,47,28,31,28,28,27,47,28,
45,246,30,28,245,29,47,47,29,30,28,47,27,1,246,47,
47,47,1,28,47,28,47,1,47,47,1,29,29,47,47,28,
28,29,1,47,1,47,47,28,31,47,47,31,47,47,47,4,
8,8,39,245,1,47,28,245,28,47,31,28,47,28,28,28,
40,8,8,8,8,8,36,47,28,1,246,47,1,40,8,8,36,1,
47,1,102,1,102,102,47,94,94,102,47,47,102,102,102,102,
94,1,94,47,102,1,102,47,30,30,102,27,47,102,94,1,
102,47,1,94,102,103,1,102,103,103,47,47,47,29,1,29,
28,28,29,28,1,47,28,31,29,1,47,29,28,1,1,47,
4,39,1,47,47,1,28,28,28,47,1,28,45,28,47,47,
1,40,4,4,40,4,29,28,31,45,47,28,47,47,4,40,28,28
};
static void
fixQuitScreen(byte* px)
{
// overwrite 11 lines, 98 pixels each, from quitscreenfix[]
// starting at line 140, column 188
// quitscreen is 320x240 px
int r, qsIdx = 0;
px += 140*320; // go to line 140
px += 188; // to colum 188
for(r=0; r<11; ++r)
{
memcpy(px, quitscreenfix+qsIdx, 98);
qsIdx += 98;
px += 320;
}
}
static void
PCX_Decode(const byte *raw, int len, byte **pic, byte **palette,
int *width, int *height, int *bytesPerPixel)
@ -152,18 +242,44 @@ VID_ImageDecode(const char *filename, byte **pic, byte **palette,
return;
}
*pic = NULL;
ident = LittleLong(*((int*)raw));
if (ident == PCX_IDENT)
{
PCX_Decode(raw, len, pic, palette, width, height, bytesPerPixel);
if(*pic && width && height
&& *width == 319 && *height == 239
&& Q_strcasecmp(filename, "pics/quit.pcx") == 0
&& Com_BlockChecksum(raw, len) == 3329419434u)
{
// it's the quit screen, and the baseq2 one (identified by checksum)
// so fix it
fixQuitScreen(*pic);
}
}
else
{
int sourceBytesPerPixel = 0;
/* other formats does not have palette directly */
*palette = NULL;
if (palette)
{
*palette = NULL;
}
*pic = stbi_load_from_memory(raw, len, width, height,
bytesPerPixel, STBI_rgb_alpha);
&sourceBytesPerPixel, STBI_rgb_alpha);
if (*pic == NULL)
{
Com_DPrintf("%s couldn't load data from %s: %s!\n",
__func__, filename, stbi_failure_reason());
return;
}
*bytesPerPixel = 4;
}
FS_FreeFile(raw);

View file

@ -447,6 +447,7 @@ VID_LoadRenderer(void)
ri.Vid_GetModeInfo = VID_GetModeInfo;
ri.Vid_MenuInit = VID_MenuInit;
ri.Vid_WriteScreenshot = VID_WriteScreenshot;
ri.VID_ImageDecode = VID_ImageDecode;
ri.Vid_RequestRestart = VID_RequestRestart;
// Exchange our export struct with the renderers import struct.