From 9f84e40ab761d0075b5369ce4d009cd2608e4156 Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Thu, 20 Jun 2024 00:41:34 +0300 Subject: [PATCH] cin: move image load to separate file --- Makefile | 1 + src/client/cl_cin.c | 134 +++++------------------ src/client/header/client.h | 2 + src/client/refresh/files/stb.c | 3 +- src/client/refresh/gl1/gl1_main.c | 30 +++--- src/client/vid/image.c | 170 ++++++++++++++++++++++++++++++ src/client/vid/vid.c | 3 +- 7 files changed, 217 insertions(+), 126 deletions(-) create mode 100644 src/client/vid/image.c diff --git a/Makefile b/Makefile index 9fd0b258..ad3040c3 100644 --- a/Makefile +++ b/Makefile @@ -1003,6 +1003,7 @@ CLIENT_OBJS_ := \ src/client/sound/sdl.o \ src/client/sound/sound.o \ src/client/sound/wave.o \ + src/client/vid/image.o \ src/client/vid/vid.o \ src/common/argproc.o \ src/common/clientserver.o \ diff --git a/src/client/cl_cin.c b/src/client/cl_cin.c index f64d0424..fa43489f 100644 --- a/src/client/cl_cin.c +++ b/src/client/cl_cin.c @@ -37,20 +37,6 @@ #define PL_MPEG_IMPLEMENTATION #include "cinema/pl_mpeg.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 "refresh/files/stb_image.h" - - extern cvar_t *vid_renderer; cvar_t *cin_force43; @@ -111,102 +97,33 @@ typedef struct cinematics_t cin; static void -SCR_LoadPCX(char *filename, byte **pic, byte **palette, int *width, int *height) +SCR_LoadPCX(char *filename, byte **pic, byte **palette, int *width, int *height, + int *bytesPerPixel) { - byte *raw; - pcx_t *pcx; - int x, y; - int len, full_size; - int dataByte, runLength; - byte *out, *pix; + byte *data, *palette_in; *pic = NULL; + *palette = NULL; - /* load the file */ - len = FS_LoadFile(filename, (void **)&raw); + VID_ImageDecode(filename, &data, &palette_in, width, height, bytesPerPixel); - if (!raw || len < sizeof(pcx_t)) + if (data) { - return; + *pic = Z_Malloc((*width) * (*height) * (*bytesPerPixel)); + memcpy(*pic, data, (*height) * (*width) * (*bytesPerPixel)); + free(data); } - - /* parse the PCX file */ - pcx = (pcx_t *)raw; - raw = &pcx->data; - - if ((pcx->manufacturer != 0x0a) || - (pcx->version != 5) || - (pcx->encoding != 1) || - (pcx->bits_per_pixel != 8) || - (pcx->xmax >= 640) || - (pcx->ymax >= 480)) + else { Com_Printf("Bad pcx file %s\n", filename); - return; } - full_size = (pcx->ymax + 1) * (pcx->xmax + 1); - out = Z_Malloc(full_size); - - *pic = out; - - pix = out; - - if (palette) + if (palette_in) { *palette = Z_Malloc(768); - memcpy(*palette, (byte *)pcx + len - 768, 768); + memcpy(*palette, palette_in, 768); + free(palette_in); } - - if (width) - { - *width = pcx->xmax + 1; - } - - if (height) - { - *height = pcx->ymax + 1; - } - - for (y = 0; y <= pcx->ymax; y++, pix += pcx->xmax + 1) - { - for (x = 0; x <= pcx->xmax; ) - { - dataByte = *raw++; - - if ((dataByte & 0xC0) == 0xC0) - { - runLength = dataByte & 0x3F; - dataByte = *raw++; - } - else - { - runLength = 1; - } - - while (runLength-- > 0) - { - if ((*pic + full_size) <= (pix + x)) - { - x += runLength; - runLength = 0; - } - else - { - pix[x++] = dataByte; - } - } - } - } - - if (raw - (byte *)pcx > len) - { - Com_Printf("PCX file %s was malformed", filename); - Z_Free(*pic); - *pic = NULL; - } - - FS_FreeFile(pcx); } void @@ -863,29 +780,25 @@ SCR_DrawCinematic(void) static byte * SCR_LoadHiColor(const char* namewe, const char *ext, int *width, int *height) { + byte *pic, *data = NULL, *palette = NULL; char filename[256]; int bytesPerPixel; - byte *pic, *data = NULL; - void *rawdata; - size_t len; Q_strlcpy(filename, namewe, sizeof(filename)); Q_strlcat(filename, ".", sizeof(filename)); Q_strlcat(filename, ext, sizeof(filename)); - len = FS_LoadFile(filename, &rawdata); - - if (!rawdata || len <=0) + VID_ImageDecode(filename, &data, &palette, + width, height, &bytesPerPixel); + if (data == NULL) { return NULL; } - data = stbi_load_from_memory(rawdata, len, width, height, - &bytesPerPixel, STBI_rgb_alpha); - if (data == NULL) + if (palette) { - FS_FreeFile(rawdata); - return NULL; + /* strange, here should be no palleted image */ + free(palette); } pic = Z_Malloc(cin.height * cin.width * 4); @@ -946,8 +859,11 @@ SCR_PlayCinematic(char *arg) if (!cin.pic) { - SCR_LoadPCX(name, &cin.pic, &palette, &cin.width, &cin.height); - cin.color_bits = 8; + int bytesPerPixel; + + SCR_LoadPCX(name, &cin.pic, &palette, &cin.width, &cin.height, + &bytesPerPixel); + cin.color_bits = 8 * bytesPerPixel; } cl.cinematicframe = -1; diff --git a/src/client/header/client.h b/src/client/header/client.h index ee7883e0..28bfc3f1 100644 --- a/src/client/header/client.h +++ b/src/client/header/client.h @@ -508,6 +508,8 @@ void V_AddEntity (entity_t *ent); void V_AddParticle (vec3_t org, unsigned int color, float alpha); void V_AddLight (vec3_t org, float intensity, float r, float g, float b); void V_AddLightStyle (int style, float r, float g, float b); +void VID_ImageDecode(const char *filename, byte **pic, byte **palette, + int *width, int *height, int *bytesPerPixel); void CL_RegisterTEntSounds (void); void CL_RegisterTEntModels (void); diff --git a/src/client/refresh/files/stb.c b/src/client/refresh/files/stb.c index be526dc6..e075276a 100644 --- a/src/client/refresh/files/stb.c +++ b/src/client/refresh/files/stb.c @@ -89,7 +89,8 @@ LoadSTB(const char *origname, const char* type, byte **pic, int *width, int *hei data = stbi_load_from_memory(rawdata, rawsize, &w, &h, &bytesPerPixel, STBI_rgb_alpha); if (data == NULL) { - R_Printf(PRINT_ALL, "%s couldn't load data from %s: %s!\n", __func__, filename, stbi_failure_reason()); + R_Printf(PRINT_ALL, "%s couldn't load data from %s: %s!\n", + __func__, filename, stbi_failure_reason()); ri.FS_FreeFile(rawdata); return false; } diff --git a/src/client/refresh/gl1/gl1_main.c b/src/client/refresh/gl1/gl1_main.c index 6c405ce6..c71777cf 100644 --- a/src/client/refresh/gl1/gl1_main.c +++ b/src/client/refresh/gl1/gl1_main.c @@ -220,27 +220,27 @@ R_DrawSpriteModel(entity_t *currententity, const model_t *currentmodel) 1, 1 }; - VectorMA( currententity->origin, -frame->origin_y, up, point[0] ); - VectorMA( point[0], -frame->origin_x, right, point[0] ); + VectorMA(currententity->origin, -frame->origin_y, up, point[0]); + VectorMA(point[0], -frame->origin_x, right, point[0]); - VectorMA( currententity->origin, frame->height - frame->origin_y, up, point[1] ); - VectorMA( point[1], -frame->origin_x, right, point[1] ); + VectorMA(currententity->origin, frame->height - frame->origin_y, up, point[1]); + VectorMA(point[1], -frame->origin_x, right, point[1]); - VectorMA( currententity->origin, frame->height - frame->origin_y, up, point[2] ); - VectorMA( point[2], frame->width - frame->origin_x, right, point[2] ); + VectorMA(currententity->origin, frame->height - frame->origin_y, up, point[2]); + VectorMA(point[2], frame->width - frame->origin_x, right, point[2]); - VectorMA( currententity->origin, -frame->origin_y, up, point[3] ); - VectorMA( point[3], frame->width - frame->origin_x, right, point[3] ); + VectorMA(currententity->origin, -frame->origin_y, up, point[3]); + VectorMA(point[3], frame->width - frame->origin_x, right, point[3]); - glEnableClientState( GL_VERTEX_ARRAY ); - glEnableClientState( GL_TEXTURE_COORD_ARRAY ); + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glVertexPointer( 3, GL_FLOAT, 0, point ); - glTexCoordPointer( 2, GL_FLOAT, 0, tex ); - glDrawArrays( GL_TRIANGLE_FAN, 0, 4 ); + glVertexPointer(3, GL_FLOAT, 0, point); + glTexCoordPointer(2, GL_FLOAT, 0, tex); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glDisableClientState( GL_VERTEX_ARRAY ); - glDisableClientState( GL_TEXTURE_COORD_ARRAY ); + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisable(GL_ALPHA_TEST); R_TexEnv(GL_REPLACE); diff --git a/src/client/vid/image.c b/src/client/vid/image.c new file mode 100644 index 00000000..201f6208 --- /dev/null +++ b/src/client/vid/image.c @@ -0,0 +1,170 @@ +/* + * Copyright (C) 1997-2001 Id Software, Inc. + * + * 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. + * + * ======================================================================= + * + * Shared image decode logic + * + * ======================================================================= + */ + +#include "../../client/header/client.h" + +#define PCX_IDENT ((0x08 << 24) + (0x01 << 16) + (0x05 << 8) + 0x0a) +// 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 "../refresh/files/stb_image.h" + +static void +PCX_Decode(const byte *raw, int len, byte **pic, byte **palette, + int *width, int *height, int *bytesPerPixel) +{ + pcx_t *pcx; + int x, y, full_size; + int dataByte, runLength; + byte *out, *pix; + + *pic = NULL; + *bytesPerPixel = 1; + + if (len < sizeof(pcx_t)) + { + return; + } + + /* parse the PCX file */ + pcx = (pcx_t *)raw; + raw = &pcx->data; + + if ((pcx->manufacturer != 0x0a) || + (pcx->version != 5) || + (pcx->encoding != 1) || + (pcx->bits_per_pixel != 8)) + { + return; + } + + full_size = (pcx->ymax + 1) * (pcx->xmax + 1); + out = malloc(full_size); + + *pic = out; + + pix = out; + + if (palette) + { + *palette = malloc(768); + memcpy(*palette, (byte *)pcx + len - 768, 768); + } + + if (width) + { + *width = pcx->xmax + 1; + } + + if (height) + { + *height = pcx->ymax + 1; + } + + for (y = 0; y <= pcx->ymax; y++, pix += pcx->xmax + 1) + { + for (x = 0; x <= pcx->xmax; ) + { + dataByte = *raw++; + + if ((dataByte & 0xC0) == 0xC0) + { + runLength = dataByte & 0x3F; + dataByte = *raw++; + } + else + { + runLength = 1; + } + + while (runLength-- > 0) + { + if ((*pic + full_size) <= (pix + x)) + { + x += runLength; + runLength = 0; + } + else + { + pix[x++] = dataByte; + } + } + } + } + + if (raw - (byte *)pcx > len) + { + free(*pic); + *pic = NULL; + } +} + + +void +VID_ImageDecode(const char *filename, byte **pic, byte **palette, + int *width, int *height, int *bytesPerPixel) +{ + int len, ident; + byte *raw; + + /* load the file */ + len = FS_LoadFile(filename, (void **)&raw); + + if (!raw || len <= 0) + { + return; + } + + if (len <= sizeof(int)) + { + FS_FreeFile(raw); + return; + } + + ident = LittleLong(*((int*)raw)); + if (ident == PCX_IDENT) + { + PCX_Decode(raw, len, pic, palette, width, height, bytesPerPixel); + } + else + { + /* other formats does not have palette directly */ + *palette = NULL; + + *pic = stbi_load_from_memory(raw, len, width, height, + bytesPerPixel, STBI_rgb_alpha); + } + + FS_FreeFile(raw); +} diff --git a/src/client/vid/vid.c b/src/client/vid/vid.c index 55faff8d..7bb7832e 100644 --- a/src/client/vid/vid.c +++ b/src/client/vid/vid.c @@ -69,7 +69,8 @@ compress_for_stbiw(unsigned char *data, int data_len, int *out_len, int quality) * RGB or RGBA. The pixels must be given row-wise, stating at the top * left. */ -void VID_WriteScreenshot(int width, int height, int comp, const void* data) +static void +VID_WriteScreenshot(int width, int height, int comp, const void* data) { char picname[80]; char checkname[MAX_OSPATH];