mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2025-01-22 01:01:18 +00:00
renders: support 24bit pcx images
Based on ffmpeg code and checked with https://samples.ffmpeg.org/image-samples/pcx/
This commit is contained in:
parent
f688ea599f
commit
8520285a10
6 changed files with 361 additions and 171 deletions
|
@ -68,19 +68,19 @@ cinematics_t cin;
|
||||||
|
|
||||||
static void
|
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 *bitesPerPixel)
|
int *bitsPerPixel)
|
||||||
{
|
{
|
||||||
byte *data, *palette_in;
|
byte *data, *palette_in;
|
||||||
|
|
||||||
*pic = NULL;
|
*pic = NULL;
|
||||||
*palette = NULL;
|
*palette = NULL;
|
||||||
|
|
||||||
SCR_LoadImageWithPalette(filename, &data, &palette_in, width, height, bitesPerPixel);
|
SCR_LoadImageWithPalette(filename, &data, &palette_in, width, height, bitsPerPixel);
|
||||||
|
|
||||||
if (data)
|
if (data)
|
||||||
{
|
{
|
||||||
*pic = Z_Malloc((*width) * (*height) * (*bitesPerPixel) / 8);
|
*pic = Z_Malloc((*width) * (*height) * (*bitsPerPixel) / 8);
|
||||||
memcpy(*pic, data, (*height) * (*width) * (*bitesPerPixel) / 8);
|
memcpy(*pic, data, (*height) * (*width) * (*bitsPerPixel) / 8);
|
||||||
free(data);
|
free(data);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -567,7 +567,7 @@ SCR_DrawCinematic(void)
|
||||||
|
|
||||||
static byte *
|
static byte *
|
||||||
SCR_LoadHiColor(const char* namewe, const char *ext, int *width, int *height,
|
SCR_LoadHiColor(const char* namewe, const char *ext, int *width, int *height,
|
||||||
int *bitesPerPixel)
|
int *bitsPerPixel)
|
||||||
{
|
{
|
||||||
byte *pic, *data = NULL, *palette = NULL;
|
byte *pic, *data = NULL, *palette = NULL;
|
||||||
char filename[256];
|
char filename[256];
|
||||||
|
@ -577,7 +577,7 @@ SCR_LoadHiColor(const char* namewe, const char *ext, int *width, int *height,
|
||||||
Q_strlcat(filename, ext, sizeof(filename));
|
Q_strlcat(filename, ext, sizeof(filename));
|
||||||
|
|
||||||
SCR_LoadImageWithPalette(filename, &data, &palette,
|
SCR_LoadImageWithPalette(filename, &data, &palette,
|
||||||
width, height, bitesPerPixel);
|
width, height, bitsPerPixel);
|
||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -589,8 +589,8 @@ SCR_LoadHiColor(const char* namewe, const char *ext, int *width, int *height,
|
||||||
free(palette);
|
free(palette);
|
||||||
}
|
}
|
||||||
|
|
||||||
pic = Z_Malloc(cin.height * cin.width * (*bitesPerPixel) / 8);
|
pic = Z_Malloc(cin.height * cin.width * (*bitsPerPixel) / 8);
|
||||||
memcpy(pic, data, cin.height * cin.width * (*bitesPerPixel) / 8);
|
memcpy(pic, data, cin.height * cin.width * (*bitsPerPixel) / 8);
|
||||||
free(data);
|
free(data);
|
||||||
|
|
||||||
return pic;
|
return pic;
|
||||||
|
|
|
@ -95,7 +95,7 @@ PCX_RLE_Decode(byte *pix, byte *pix_max, const byte *raw, const byte *raw_max,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
PCX_Decode(const char *name, const byte *raw, int len, byte **pic, byte **palette,
|
PCX_Decode(const char *name, const byte *raw, int len, byte **pic, byte **palette,
|
||||||
int *width, int *height, int *bitesPerPixel)
|
int *width, int *height, int *bitsPerPixel)
|
||||||
{
|
{
|
||||||
const pcx_t *pcx;
|
const pcx_t *pcx;
|
||||||
int full_size;
|
int full_size;
|
||||||
|
@ -105,7 +105,7 @@ PCX_Decode(const char *name, const byte *raw, int len, byte **pic, byte **palett
|
||||||
const byte *data;
|
const byte *data;
|
||||||
|
|
||||||
*pic = NULL;
|
*pic = NULL;
|
||||||
*bitesPerPixel = 8;
|
*bitsPerPixel = 8;
|
||||||
|
|
||||||
if (palette)
|
if (palette)
|
||||||
{
|
{
|
||||||
|
@ -144,7 +144,7 @@ PCX_Decode(const char *name, const byte *raw, int len, byte **pic, byte **palett
|
||||||
if (pcx->color_planes == 3 && pcx->bits_per_pixel == 8)
|
if (pcx->color_planes == 3 && pcx->bits_per_pixel == 8)
|
||||||
{
|
{
|
||||||
full_size *= 4;
|
full_size *= 4;
|
||||||
*bitesPerPixel = 32;
|
*bitsPerPixel = 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
out = malloc(full_size);
|
out = malloc(full_size);
|
||||||
|
@ -366,7 +366,7 @@ PCX_Decode(const char *name, const byte *raw, int len, byte **pic, byte **palett
|
||||||
|
|
||||||
void
|
void
|
||||||
SCR_LoadImageWithPalette(char *filename, byte **pic, byte **palette,
|
SCR_LoadImageWithPalette(char *filename, byte **pic, byte **palette,
|
||||||
int *width, int *height, int *bitesPerPixel)
|
int *width, int *height, int *bitsPerPixel)
|
||||||
{
|
{
|
||||||
const char* ext;
|
const char* ext;
|
||||||
int len, ident;
|
int len, ident;
|
||||||
|
@ -392,11 +392,11 @@ SCR_LoadImageWithPalette(char *filename, byte **pic, byte **palette,
|
||||||
ident = LittleShort(*((short*)raw));
|
ident = LittleShort(*((short*)raw));
|
||||||
if (!strcmp(ext, "pcx") && (ident == PCX_IDENT))
|
if (!strcmp(ext, "pcx") && (ident == PCX_IDENT))
|
||||||
{
|
{
|
||||||
PCX_Decode(filename, raw, len, pic, palette, width, height, bitesPerPixel);
|
PCX_Decode(filename, raw, len, pic, palette, width, height, bitsPerPixel);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int sourcebitesPerPixel = 0;
|
int sourcebitsPerPixel = 0;
|
||||||
|
|
||||||
/* other formats does not have palette directly */
|
/* other formats does not have palette directly */
|
||||||
if (palette)
|
if (palette)
|
||||||
|
@ -405,7 +405,7 @@ SCR_LoadImageWithPalette(char *filename, byte **pic, byte **palette,
|
||||||
}
|
}
|
||||||
|
|
||||||
*pic = stbi_load_from_memory(raw, len, width, height,
|
*pic = stbi_load_from_memory(raw, len, width, height,
|
||||||
&sourcebitesPerPixel, STBI_rgb_alpha);
|
&sourcebitsPerPixel, STBI_rgb_alpha);
|
||||||
|
|
||||||
if (*pic == NULL)
|
if (*pic == NULL)
|
||||||
{
|
{
|
||||||
|
@ -413,7 +413,7 @@ SCR_LoadImageWithPalette(char *filename, byte **pic, byte **palette,
|
||||||
__func__, filename, stbi_failure_reason());
|
__func__, filename, stbi_failure_reason());
|
||||||
}
|
}
|
||||||
|
|
||||||
*bitesPerPixel = 32;
|
*bitsPerPixel = 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
FS_FreeFile(raw);
|
FS_FreeFile(raw);
|
||||||
|
|
|
@ -60,7 +60,7 @@ void SCR_AddDirtyPoint(int x, int y);
|
||||||
void SCR_DirtyScreen(void);
|
void SCR_DirtyScreen(void);
|
||||||
|
|
||||||
void SCR_LoadImageWithPalette(char *filename, byte **pic, byte **palette,
|
void SCR_LoadImageWithPalette(char *filename, byte **pic, byte **palette,
|
||||||
int *width, int *height, int *bitesPerPixel);
|
int *width, int *height, int *bitsPerPixel);
|
||||||
void SCR_PlayCinematic(char *name);
|
void SCR_PlayCinematic(char *name);
|
||||||
qboolean SCR_DrawCinematic(void);
|
qboolean SCR_DrawCinematic(void);
|
||||||
void SCR_RunCinematic(void);
|
void SCR_RunCinematic(void);
|
||||||
|
|
|
@ -116,18 +116,338 @@ fixQuitScreen(byte* px)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static const byte *
|
||||||
LoadPCX(const char *origname, byte **pic, byte **palette, int *width, int *height)
|
PCX_RLE_Decode(byte *pix, byte *pix_max, const byte *raw, const byte *raw_max,
|
||||||
|
int bytes_per_line, qboolean *image_issues)
|
||||||
{
|
{
|
||||||
byte *raw;
|
int x;
|
||||||
pcx_t *pcx;
|
|
||||||
int x, y;
|
for (x = 0; x < bytes_per_line; )
|
||||||
int len, full_size;
|
{
|
||||||
int pcx_width, pcx_height;
|
int runLength;
|
||||||
|
byte dataByte;
|
||||||
|
|
||||||
|
if (raw >= raw_max)
|
||||||
|
{
|
||||||
|
// no place for read
|
||||||
|
*image_issues = true;
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
dataByte = *raw++;
|
||||||
|
|
||||||
|
if ((dataByte & 0xC0) == 0xC0)
|
||||||
|
{
|
||||||
|
runLength = dataByte & 0x3F;
|
||||||
|
if (raw >= raw_max)
|
||||||
|
{
|
||||||
|
// no place for read
|
||||||
|
*image_issues = true;
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
dataByte = *raw++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
runLength = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (runLength-- > 0)
|
||||||
|
{
|
||||||
|
if (pix_max <= (pix + x))
|
||||||
|
{
|
||||||
|
// no place for write
|
||||||
|
*image_issues = true;
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pix[x++] = dataByte;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
PCX_Decode(const char *name, const byte *raw, int len, byte **pic, byte **palette,
|
||||||
|
int *width, int *height, int *bitsPerPixel)
|
||||||
|
{
|
||||||
|
const pcx_t *pcx;
|
||||||
|
int full_size;
|
||||||
|
int pcx_width, pcx_height, bytes_per_line;
|
||||||
qboolean image_issues = false;
|
qboolean image_issues = false;
|
||||||
int dataByte, runLength;
|
|
||||||
byte *out, *pix;
|
byte *out, *pix;
|
||||||
|
const byte *data;
|
||||||
|
|
||||||
|
*pic = NULL;
|
||||||
|
*bitsPerPixel = 8;
|
||||||
|
|
||||||
|
if (palette)
|
||||||
|
{
|
||||||
|
*palette = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len < sizeof(pcx_t))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse the PCX file */
|
||||||
|
pcx = (const pcx_t *)raw;
|
||||||
|
|
||||||
|
data = &pcx->data;
|
||||||
|
|
||||||
|
bytes_per_line = LittleShort(pcx->bytes_per_line);
|
||||||
|
pcx_width = LittleShort(pcx->xmax) - LittleShort(pcx->xmin);
|
||||||
|
pcx_height = LittleShort(pcx->ymax) - LittleShort(pcx->ymin);
|
||||||
|
|
||||||
|
if ((pcx->manufacturer != 0x0a) ||
|
||||||
|
(pcx->version != 5) ||
|
||||||
|
(pcx->encoding != 1) ||
|
||||||
|
(pcx_width <= 0) ||
|
||||||
|
(pcx_height <= 0) ||
|
||||||
|
(bytes_per_line <= 0) ||
|
||||||
|
(pcx->color_planes <= 0) ||
|
||||||
|
(pcx->bits_per_pixel <= 0))
|
||||||
|
{
|
||||||
|
R_Printf(PRINT_ALL, "%s: Bad pcx file %s: version: %d:%d, encoding: %d\n",
|
||||||
|
__func__, name, pcx->manufacturer, pcx->version, pcx->encoding);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
full_size = (pcx_height + 1) * (pcx_width + 1);
|
||||||
|
if (pcx->color_planes == 3 && pcx->bits_per_pixel == 8)
|
||||||
|
{
|
||||||
|
full_size *= 4;
|
||||||
|
*bitsPerPixel = 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
out = malloc(full_size);
|
||||||
|
if (!out)
|
||||||
|
{
|
||||||
|
R_Printf(PRINT_ALL, "%s: Can't allocate for %s\n", __func__, name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pic = out;
|
||||||
|
|
||||||
|
pix = out;
|
||||||
|
|
||||||
|
if (width)
|
||||||
|
{
|
||||||
|
*width = pcx_width + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (height)
|
||||||
|
{
|
||||||
|
*height = pcx_height + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((pcx->color_planes == 3 || pcx->color_planes == 4)
|
||||||
|
&& pcx->bits_per_pixel == 8)
|
||||||
|
{
|
||||||
|
int x, y, linesize;
|
||||||
|
byte *line;
|
||||||
|
|
||||||
|
if (bytes_per_line <= pcx_width)
|
||||||
|
{
|
||||||
|
image_issues = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clean image alpha */
|
||||||
|
memset(pix, 255, full_size);
|
||||||
|
|
||||||
|
linesize = Q_max(bytes_per_line, pcx_width + 1) * pcx->color_planes;
|
||||||
|
line = malloc(linesize);
|
||||||
|
|
||||||
|
for (y = 0; y <= pcx_height; y++, pix += (pcx_width + 1) * 4)
|
||||||
|
{
|
||||||
|
data = PCX_RLE_Decode(line, line + linesize,
|
||||||
|
data, (byte *)pcx + len,
|
||||||
|
bytes_per_line * pcx->color_planes, &image_issues);
|
||||||
|
|
||||||
|
for (x = 0; x <= pcx_width; x++) {
|
||||||
|
int j;
|
||||||
|
|
||||||
|
for (j = 0; j < pcx->color_planes; j++)
|
||||||
|
{
|
||||||
|
pix[4 * x + j] = line[x + bytes_per_line * j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(line);
|
||||||
|
}
|
||||||
|
else if (pcx->bits_per_pixel == 1)
|
||||||
|
{
|
||||||
|
byte *line;
|
||||||
|
int y;
|
||||||
|
|
||||||
|
if (palette)
|
||||||
|
{
|
||||||
|
*palette = malloc(768);
|
||||||
|
|
||||||
|
if (!(*palette))
|
||||||
|
{
|
||||||
|
R_Printf(PRINT_ALL, "%s: Can't allocate for %s\n", __func__, name);
|
||||||
|
free(out);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(*palette, pcx->palette, sizeof(pcx->palette));
|
||||||
|
}
|
||||||
|
|
||||||
|
line = malloc(bytes_per_line * pcx->color_planes);
|
||||||
|
|
||||||
|
for (y = 0; y <= pcx_height; y++, pix += pcx_width + 1)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
|
||||||
|
data = PCX_RLE_Decode(line, line + bytes_per_line * pcx->color_planes,
|
||||||
|
data, (byte *)pcx + len,
|
||||||
|
bytes_per_line * pcx->color_planes, &image_issues);
|
||||||
|
|
||||||
|
for (x = 0; x <= pcx_width; x++)
|
||||||
|
{
|
||||||
|
int m, i, v;
|
||||||
|
|
||||||
|
m = 0x80 >> (x & 7);
|
||||||
|
v = 0;
|
||||||
|
|
||||||
|
for (i = pcx->color_planes - 1; i >= 0; i--) {
|
||||||
|
v <<= 1;
|
||||||
|
v += (line[i * bytes_per_line + (x >> 3)] & m) ? 1 : 0;
|
||||||
|
}
|
||||||
|
pix[x] = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(line);
|
||||||
|
}
|
||||||
|
else if (pcx->color_planes == 1 && pcx->bits_per_pixel == 8)
|
||||||
|
{
|
||||||
|
int y, linesize;
|
||||||
|
byte *line;
|
||||||
|
|
||||||
|
if (palette)
|
||||||
|
{
|
||||||
|
*palette = malloc(768);
|
||||||
|
|
||||||
|
if (!(*palette))
|
||||||
|
{
|
||||||
|
R_Printf(PRINT_ALL, "%s: Can't allocate for %s\n", __func__, name);
|
||||||
|
free(out);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((len > 768) && (((byte *)pcx)[len - 769] == 0x0C))
|
||||||
|
{
|
||||||
|
memcpy(*palette, (byte *)pcx + len - 768, 768);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
image_issues = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bytes_per_line <= pcx_width)
|
||||||
|
{
|
||||||
|
image_issues = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
linesize = Q_max(bytes_per_line, pcx_width + 1);
|
||||||
|
line = malloc(linesize);
|
||||||
|
for (y = 0; y <= pcx_height; y++, pix += pcx_width + 1)
|
||||||
|
{
|
||||||
|
data = PCX_RLE_Decode(line, line + linesize,
|
||||||
|
data, (byte *)pcx + len,
|
||||||
|
bytes_per_line, &image_issues);
|
||||||
|
/* copy only visible part */
|
||||||
|
memcpy(pix, line, pcx_width + 1);
|
||||||
|
}
|
||||||
|
free(line);
|
||||||
|
}
|
||||||
|
else if (pcx->color_planes == 1 &&
|
||||||
|
(pcx->bits_per_pixel == 2 || pcx->bits_per_pixel == 4))
|
||||||
|
{
|
||||||
|
int y;
|
||||||
|
|
||||||
|
byte *line;
|
||||||
|
|
||||||
|
if (palette)
|
||||||
|
{
|
||||||
|
*palette = malloc(768);
|
||||||
|
|
||||||
|
if (!(*palette))
|
||||||
|
{
|
||||||
|
R_Printf(PRINT_ALL, "%s: Can't allocate for %s\n", __func__, name);
|
||||||
|
free(out);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(*palette, pcx->palette, sizeof(pcx->palette));
|
||||||
|
}
|
||||||
|
|
||||||
|
line = malloc(bytes_per_line);
|
||||||
|
|
||||||
|
for (y = 0; y <= pcx_height; y++, pix += pcx_width + 1)
|
||||||
|
{
|
||||||
|
int x, mask, div;
|
||||||
|
|
||||||
|
data = PCX_RLE_Decode(line, line + bytes_per_line,
|
||||||
|
data, (byte *)pcx + len,
|
||||||
|
bytes_per_line, &image_issues);
|
||||||
|
|
||||||
|
mask = (1 << pcx->bits_per_pixel) - 1;
|
||||||
|
div = 8 / pcx->bits_per_pixel;
|
||||||
|
|
||||||
|
for (x = 0; x <= pcx_width; x++)
|
||||||
|
{
|
||||||
|
unsigned v, shift;
|
||||||
|
|
||||||
|
v = line[x / div] & 0xFF;
|
||||||
|
/* for 2 bits:
|
||||||
|
* 0 -> 6
|
||||||
|
* 1 -> 4
|
||||||
|
* 3 -> 2
|
||||||
|
* 4 -> 0
|
||||||
|
*/
|
||||||
|
shift = pcx->bits_per_pixel * ((div - 1) - x % div);
|
||||||
|
pix[x] = (v >> shift) & mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(line);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
R_Printf(PRINT_ALL, "%s: Bad pcx file %s: planes: %d, bits: %d\n",
|
||||||
|
__func__, name, pcx->color_planes, pcx->bits_per_pixel);
|
||||||
|
free(*pic);
|
||||||
|
*pic = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data - (byte *)pcx > len)
|
||||||
|
{
|
||||||
|
R_Printf(PRINT_DEVELOPER, "%s: %s file was malformed\n",
|
||||||
|
__func__, name);
|
||||||
|
free(*pic);
|
||||||
|
*pic = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (image_issues)
|
||||||
|
{
|
||||||
|
R_Printf(PRINT_ALL, "%s: %s file has possible size issues.\n",
|
||||||
|
__func__, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LoadPCX(const char *origname, byte **pic, byte **palette, int *width, int *height,
|
||||||
|
int *bitsPerPixel)
|
||||||
|
{
|
||||||
char filename[256];
|
char filename[256];
|
||||||
|
byte *raw;
|
||||||
|
int len;
|
||||||
|
|
||||||
FixFileExt(origname, "pcx", filename, sizeof(filename));
|
FixFileExt(origname, "pcx", filename, sizeof(filename));
|
||||||
|
|
||||||
|
@ -140,156 +460,25 @@ LoadPCX(const char *origname, byte **pic, byte **palette, int *width, int *heigh
|
||||||
|
|
||||||
/* load the file */
|
/* load the file */
|
||||||
len = ri.FS_LoadFile(filename, (void **)&raw);
|
len = ri.FS_LoadFile(filename, (void **)&raw);
|
||||||
|
if (!raw)
|
||||||
if (!raw || len < sizeof(pcx_t))
|
|
||||||
{
|
{
|
||||||
R_Printf(PRINT_DEVELOPER, "Bad pcx file %s\n", filename);
|
/* no such file */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse the PCX file */
|
PCX_Decode(filename, raw, len, pic, palette, width, height, bitsPerPixel);
|
||||||
pcx = (pcx_t *)raw;
|
|
||||||
|
|
||||||
pcx->xmin = LittleShort(pcx->xmin);
|
if(*pic && *bitsPerPixel == 8 && width && height
|
||||||
pcx->ymin = LittleShort(pcx->ymin);
|
&& *width == 319 && *height == 239
|
||||||
pcx->xmax = LittleShort(pcx->xmax);
|
&& Q_strcasecmp(filename, "pics/quit.pcx") == 0
|
||||||
pcx->ymax = LittleShort(pcx->ymax);
|
&& Com_BlockChecksum(raw, len) == 3329419434u)
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pcx->bytes_per_line <= pcx_width)
|
|
||||||
{
|
|
||||||
pcx->bytes_per_line = pcx_width + 1;
|
|
||||||
image_issues = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
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->bytes_per_line; )
|
|
||||||
{
|
|
||||||
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)
|
// it's the quit screen, and the baseq2 one (identified by checksum)
|
||||||
// so fix it
|
// so fix it
|
||||||
fixQuitScreen(*pic);
|
fixQuitScreen(*pic);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (image_issues)
|
ri.FS_FreeFile(raw);
|
||||||
{
|
|
||||||
R_Printf(PRINT_ALL, "PCX file %s has possible size issues.\n", filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
ri.FS_FreeFile(pcx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -327,11 +516,11 @@ void
|
||||||
GetPCXPalette (byte **colormap, unsigned *d_8to24table)
|
GetPCXPalette (byte **colormap, unsigned *d_8to24table)
|
||||||
{
|
{
|
||||||
byte *pal;
|
byte *pal;
|
||||||
int i;
|
int i, bitsPerPixel;
|
||||||
|
|
||||||
/* get the palette and colormap */
|
/* get the palette and colormap */
|
||||||
LoadPCX ("pics/colormap.pcx", colormap, &pal, NULL, NULL);
|
LoadPCX ("pics/colormap.pcx", colormap, &pal, NULL, NULL, &bitsPerPixel);
|
||||||
if (!*colormap || !pal)
|
if (!*colormap || !pal || bitsPerPixel != 8)
|
||||||
{
|
{
|
||||||
ri.Sys_Error (ERR_FATAL, "%s: Couldn't load pics/colormap.pcx",
|
ri.Sys_Error (ERR_FATAL, "%s: Couldn't load pics/colormap.pcx",
|
||||||
__func__);
|
__func__);
|
||||||
|
|
|
@ -509,16 +509,16 @@ R_LoadImage(const char *name, const char* namewe, const char *ext, imagetype_t t
|
||||||
{
|
{
|
||||||
byte *pic = NULL;
|
byte *pic = NULL;
|
||||||
byte *palette = NULL;
|
byte *palette = NULL;
|
||||||
int width = 0, height = 0;
|
int width = 0, height = 0, bitsPerPixel = 8;
|
||||||
|
|
||||||
LoadPCX (namewe, &pic, &palette, &width, &height);
|
LoadPCX (namewe, &pic, &palette, &width, &height, &bitsPerPixel);
|
||||||
if (!pic)
|
if (!pic)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
image = load_image(name, pic,
|
image = load_image(name, pic,
|
||||||
width, width,
|
width, width,
|
||||||
height, height,
|
height, height,
|
||||||
width * height, type, 8);
|
width * height, type, bitsPerPixel);
|
||||||
|
|
||||||
if (palette)
|
if (palette)
|
||||||
{
|
{
|
||||||
|
|
|
@ -85,7 +85,8 @@ extern struct image_s* LoadM8(const char *origname, imagetype_t type, loadimage_
|
||||||
extern struct image_s* LoadM32(const char *origname, imagetype_t type, loadimage_t load_image);
|
extern struct image_s* LoadM32(const char *origname, imagetype_t type, loadimage_t load_image);
|
||||||
extern void FixFileExt(const char *origname, const char *ext, char *filename, size_t size);
|
extern void FixFileExt(const char *origname, const char *ext, char *filename, size_t size);
|
||||||
extern void GetPCXPalette(byte **colormap, unsigned *d_8to24table);
|
extern void GetPCXPalette(byte **colormap, unsigned *d_8to24table);
|
||||||
extern void LoadPCX(const char *origname, byte **pic, byte **palette, int *width, int *height);
|
extern void LoadPCX(const char *origname, byte **pic, byte **palette, int *width, int *height,
|
||||||
|
int *bitsPerPixel);
|
||||||
extern void GetPCXInfo(const char *origname, int *width, int *height);
|
extern void GetPCXInfo(const char *origname, int *width, int *height);
|
||||||
extern void GetWalInfo(const char *name, int *width, int *height);
|
extern void GetWalInfo(const char *name, int *width, int *height);
|
||||||
extern void GetM8Info(const char *name, int *width, int *height);
|
extern void GetM8Info(const char *name, int *width, int *height);
|
||||||
|
|
Loading…
Reference in a new issue