mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-04-27 20:41:46 +00:00
PNG support
This commit is contained in:
parent
666d20c9e3
commit
75165ebb28
6 changed files with 508 additions and 33 deletions
|
|
@ -536,4 +536,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
|
||||||
/// SRB2CB itself ported this from PrBoom+
|
/// SRB2CB itself ported this from PrBoom+
|
||||||
#define NEWCLIP
|
#define NEWCLIP
|
||||||
|
|
||||||
|
//#define NO_PNG_LUMPS
|
||||||
|
|
||||||
#endif // __DOOMDEF__
|
#endif // __DOOMDEF__
|
||||||
|
|
|
||||||
|
|
@ -451,7 +451,10 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex)
|
||||||
// Composite the columns together.
|
// Composite the columns together.
|
||||||
for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++)
|
for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++)
|
||||||
{
|
{
|
||||||
|
size_t lumplength = W_LumpLengthPwad(patch->wad, patch->lump);
|
||||||
realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE);
|
realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE);
|
||||||
|
if (R_IsLumpPNG((UINT8 *)realpatch, lumplength))
|
||||||
|
realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength);
|
||||||
HWR_DrawPatchInCache(&grtex->mipmap,
|
HWR_DrawPatchInCache(&grtex->mipmap,
|
||||||
blockwidth, blockheight,
|
blockwidth, blockheight,
|
||||||
blockwidth*format2bpp[grtex->mipmap.grInfo.format],
|
blockwidth*format2bpp[grtex->mipmap.grInfo.format],
|
||||||
|
|
@ -683,11 +686,14 @@ lumpnum_t gr_patchflat;
|
||||||
static void HWR_LoadPatchFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
|
static void HWR_LoadPatchFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
|
||||||
{
|
{
|
||||||
patch_t *patch = (patch_t *)W_CacheLumpNum(flatlumpnum, PU_STATIC);
|
patch_t *patch = (patch_t *)W_CacheLumpNum(flatlumpnum, PU_STATIC);
|
||||||
|
size_t lumplength = W_LumpLength(flatlumpnum);
|
||||||
|
if (R_IsLumpPNG((UINT8 *)patch, lumplength))
|
||||||
|
patch = R_PNGToPatch((UINT8 *)patch, lumplength);
|
||||||
|
|
||||||
grMipmap->width = (UINT16)SHORT(patch->width);
|
grMipmap->width = (UINT16)SHORT(patch->width);
|
||||||
grMipmap->height = (UINT16)SHORT(patch->height);
|
grMipmap->height = (UINT16)SHORT(patch->height);
|
||||||
|
|
||||||
R_FlatPatch(patch, Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data));
|
R_PatchToFlat(patch, Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
|
static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
|
||||||
|
|
@ -777,7 +783,7 @@ static void HWR_LoadTextureFlat(GLMipmap_t *grMipmap, INT32 texturenum)
|
||||||
grMipmap->width = (UINT16)textures[texturenum]->width;
|
grMipmap->width = (UINT16)textures[texturenum]->width;
|
||||||
grMipmap->height = (UINT16)textures[texturenum]->height;
|
grMipmap->height = (UINT16)textures[texturenum]->height;
|
||||||
|
|
||||||
R_FlatTexture(texturenum, Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data));
|
R_TextureToFlat(texturenum, Z_Malloc(grMipmap->width * grMipmap->height, PU_HWRCACHE, &grMipmap->grInfo.data));
|
||||||
}
|
}
|
||||||
|
|
||||||
void HWR_GetTextureFlat(INT32 texturenum)
|
void HWR_GetTextureFlat(INT32 texturenum)
|
||||||
|
|
|
||||||
459
src/r_data.c
459
src/r_data.c
|
|
@ -40,6 +40,28 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_PNG
|
||||||
|
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
#ifndef _LARGEFILE64_SOURCE
|
||||||
|
#define _LARGEFILE64_SOURCE
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _LFS64_LARGEFILE
|
||||||
|
#define _LFS64_LARGEFILE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _FILE_OFFSET_BITS
|
||||||
|
#define _FILE_OFFSET_BITS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "png.h"
|
||||||
|
#ifndef PNG_READ_SUPPORTED
|
||||||
|
#undef HAVE_PNG
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
// Texture definition.
|
// Texture definition.
|
||||||
// Each texture is composed of one or more patches,
|
// Each texture is composed of one or more patches,
|
||||||
|
|
@ -178,7 +200,7 @@ static inline void R_DrawColumnInCache(column_t *patch, UINT8 *cache, INT32 orig
|
||||||
// Allocate space for full size texture, either single patch or 'composite'
|
// Allocate space for full size texture, either single patch or 'composite'
|
||||||
// Build the full textures from patches.
|
// Build the full textures from patches.
|
||||||
// The texture caching system is a little more hungry of memory, but has
|
// The texture caching system is a little more hungry of memory, but has
|
||||||
// been simplified for the sake of highcolor, dynamic ligthing, & speed.
|
// been simplified for the sake of highcolor (lol), dynamic ligthing, & speed.
|
||||||
//
|
//
|
||||||
// This is not optimised, but it's supposed to be executed only once
|
// This is not optimised, but it's supposed to be executed only once
|
||||||
// per level, when enough memory is available.
|
// per level, when enough memory is available.
|
||||||
|
|
@ -195,6 +217,10 @@ static UINT8 *R_GenerateTexture(size_t texnum)
|
||||||
column_t *patchcol;
|
column_t *patchcol;
|
||||||
UINT32 *colofs;
|
UINT32 *colofs;
|
||||||
|
|
||||||
|
UINT16 wadnum;
|
||||||
|
lumpnum_t lumpnum;
|
||||||
|
size_t lumplength;
|
||||||
|
|
||||||
I_Assert(texnum <= (size_t)numtextures);
|
I_Assert(texnum <= (size_t)numtextures);
|
||||||
texture = textures[texnum];
|
texture = textures[texnum];
|
||||||
I_Assert(texture != NULL);
|
I_Assert(texture != NULL);
|
||||||
|
|
@ -209,7 +235,13 @@ static UINT8 *R_GenerateTexture(size_t texnum)
|
||||||
{
|
{
|
||||||
boolean holey = false;
|
boolean holey = false;
|
||||||
patch = texture->patches;
|
patch = texture->patches;
|
||||||
realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE);
|
|
||||||
|
wadnum = patch->wad;
|
||||||
|
lumpnum = patch->lump;
|
||||||
|
lumplength = W_LumpLengthPwad(wadnum, lumpnum);
|
||||||
|
realpatch = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
|
||||||
|
if (R_IsLumpPNG((UINT8 *)realpatch, lumplength))
|
||||||
|
realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength);
|
||||||
|
|
||||||
// Check the patch for holes.
|
// Check the patch for holes.
|
||||||
if (texture->width > SHORT(realpatch->width) || texture->height > SHORT(realpatch->height))
|
if (texture->width > SHORT(realpatch->width) || texture->height > SHORT(realpatch->height))
|
||||||
|
|
@ -238,7 +270,7 @@ static UINT8 *R_GenerateTexture(size_t texnum)
|
||||||
if (holey)
|
if (holey)
|
||||||
{
|
{
|
||||||
texture->holes = true;
|
texture->holes = true;
|
||||||
blocksize = W_LumpLengthPwad(patch->wad, patch->lump);
|
blocksize = lumplength;
|
||||||
block = Z_Calloc(blocksize, PU_STATIC, // will change tag at end of this function
|
block = Z_Calloc(blocksize, PU_STATIC, // will change tag at end of this function
|
||||||
&texturecache[texnum]);
|
&texturecache[texnum]);
|
||||||
M_Memcpy(block, realpatch, blocksize);
|
M_Memcpy(block, realpatch, blocksize);
|
||||||
|
|
@ -274,7 +306,13 @@ static UINT8 *R_GenerateTexture(size_t texnum)
|
||||||
// Composite the columns together.
|
// Composite the columns together.
|
||||||
for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++)
|
for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++)
|
||||||
{
|
{
|
||||||
realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE);
|
wadnum = patch->wad;
|
||||||
|
lumpnum = patch->lump;
|
||||||
|
lumplength = W_LumpLengthPwad(wadnum, lumpnum);
|
||||||
|
realpatch = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
|
||||||
|
if (R_IsLumpPNG((UINT8 *)realpatch, lumplength))
|
||||||
|
realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength);
|
||||||
|
|
||||||
x1 = patch->originx;
|
x1 = patch->originx;
|
||||||
x2 = x1 + SHORT(realpatch->width);
|
x2 = x1 + SHORT(realpatch->width);
|
||||||
|
|
||||||
|
|
@ -487,7 +525,10 @@ void R_LoadTextures(void)
|
||||||
// Work through each lump between the markers in the WAD.
|
// Work through each lump between the markers in the WAD.
|
||||||
for (j = 0; j < (texend - texstart); i++, j++)
|
for (j = 0; j < (texend - texstart); i++, j++)
|
||||||
{
|
{
|
||||||
patchlump = W_CacheLumpNumPwad((UINT16)w, texstart + j, PU_CACHE);
|
UINT16 wadnum = (UINT16)w;
|
||||||
|
lumpnum_t lumpnum = texstart + j;
|
||||||
|
size_t lumplength = W_LumpLengthPwad(wadnum, lumpnum);
|
||||||
|
patchlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
|
||||||
|
|
||||||
// Then, check the lump directly to see if it's a texture SOC,
|
// Then, check the lump directly to see if it's a texture SOC,
|
||||||
// and if it is, load it using dehacked instead.
|
// and if it is, load it using dehacked instead.
|
||||||
|
|
@ -503,9 +544,19 @@ void R_LoadTextures(void)
|
||||||
texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL);
|
texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL);
|
||||||
|
|
||||||
// Set texture properties.
|
// Set texture properties.
|
||||||
M_Memcpy(texture->name, W_CheckNameForNumPwad((UINT16)w, texstart + j), sizeof(texture->name));
|
M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name));
|
||||||
texture->width = SHORT(patchlump->width);
|
if (R_IsLumpPNG((UINT8 *)patchlump, lumplength))
|
||||||
texture->height = SHORT(patchlump->height);
|
{
|
||||||
|
INT16 width, height;
|
||||||
|
R_PNGDimensions((UINT8 *)patchlump, &width, &height, lumplength);
|
||||||
|
texture->width = width;
|
||||||
|
texture->height = height;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
texture->width = SHORT(patchlump->width);
|
||||||
|
texture->height = SHORT(patchlump->height);
|
||||||
|
}
|
||||||
texture->patchcount = 1;
|
texture->patchcount = 1;
|
||||||
texture->holes = false;
|
texture->holes = false;
|
||||||
|
|
||||||
|
|
@ -1178,7 +1229,6 @@ INT32 R_ColormapNumForName(char *name)
|
||||||
//
|
//
|
||||||
static double deltas[256][3], map[256][3];
|
static double deltas[256][3], map[256][3];
|
||||||
|
|
||||||
static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b);
|
|
||||||
static int RoundUp(double number);
|
static int RoundUp(double number);
|
||||||
|
|
||||||
INT32 R_CreateColormap(char *p1, char *p2, char *p3)
|
INT32 R_CreateColormap(char *p1, char *p2, char *p3)
|
||||||
|
|
@ -1358,7 +1408,7 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3)
|
||||||
|
|
||||||
// Thanks to quake2 source!
|
// Thanks to quake2 source!
|
||||||
// utils3/qdata/images.c
|
// utils3/qdata/images.c
|
||||||
static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b)
|
UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b)
|
||||||
{
|
{
|
||||||
int dr, dg, db;
|
int dr, dg, db;
|
||||||
int distortion, bestdistortion = 256 * 256 * 4, bestcolor = 0, i;
|
int distortion, bestdistortion = 256 * 256 * 4, bestcolor = 0, i;
|
||||||
|
|
@ -1686,7 +1736,7 @@ boolean R_CheckIfPatch(lumpnum_t lump)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void R_FlatPatch(patch_t *patch, UINT8 *flat)
|
void R_PatchToFlat(patch_t *patch, UINT8 *flat)
|
||||||
{
|
{
|
||||||
fixed_t col, ofs;
|
fixed_t col, ofs;
|
||||||
column_t *column;
|
column_t *column;
|
||||||
|
|
@ -1721,7 +1771,392 @@ void R_FlatPatch(patch_t *patch, UINT8 *flat)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void R_FlatTexture(size_t tex, UINT8 *flat)
|
#ifndef NO_PNG_LUMPS
|
||||||
|
boolean R_IsLumpPNG(UINT8 *d, size_t s)
|
||||||
|
{
|
||||||
|
if (s < 67) // http://garethrees.org/2007/11/14/pngcrush/
|
||||||
|
return false;
|
||||||
|
// Check for PNG file signature using memcmp
|
||||||
|
// As it may be faster on CPUs with slow unaligned memory access
|
||||||
|
// Ref: http://www.libpng.org/pub/png/spec/1.2/PNG-Rationale.html#R.PNG-file-signature
|
||||||
|
return (memcmp(&d[0], "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", 8) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_PNG
|
||||||
|
typedef struct {
|
||||||
|
png_bytep buffer;
|
||||||
|
png_uint_32 bufsize;
|
||||||
|
png_uint_32 current_pos;
|
||||||
|
} png_ioread;
|
||||||
|
|
||||||
|
static void PNG_IOReader(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||||
|
{
|
||||||
|
png_ioread *f = png_get_io_ptr(png_ptr);
|
||||||
|
if (length > (f->bufsize - f->current_pos))
|
||||||
|
png_error(png_ptr, "read error in read_data_memory (loadpng)");
|
||||||
|
memcpy(data, f->buffer + f->current_pos, length);
|
||||||
|
f->current_pos += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PNG_error(png_structp PNG, png_const_charp pngtext)
|
||||||
|
{
|
||||||
|
CONS_Debug(DBG_RENDER, "libpng error at %p: %s", PNG, pngtext);
|
||||||
|
//I_Error("libpng error at %p: %s", PNG, pngtext);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PNG_warn(png_structp PNG, png_const_charp pngtext)
|
||||||
|
{
|
||||||
|
CONS_Debug(DBG_RENDER, "libpng warning at %p: %s", PNG, pngtext);
|
||||||
|
}
|
||||||
|
|
||||||
|
static png_bytep *PNG_Read(UINT8 *png, UINT16 *w, UINT16 *h, size_t size)
|
||||||
|
{
|
||||||
|
png_structp png_ptr;
|
||||||
|
png_infop png_info_ptr;
|
||||||
|
png_uint_32 width, height;
|
||||||
|
int bit_depth, color_type;
|
||||||
|
png_uint_32 y;
|
||||||
|
#ifdef PNG_SETJMP_SUPPORTED
|
||||||
|
#ifdef USE_FAR_KEYWORD
|
||||||
|
jmp_buf jmpbuf;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
png_ioread png_io;
|
||||||
|
png_bytep *row_pointers;
|
||||||
|
|
||||||
|
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
|
||||||
|
PNG_error, PNG_warn);
|
||||||
|
if (!png_ptr)
|
||||||
|
{
|
||||||
|
CONS_Debug(DBG_RENDER, "PNG_Load: Error on initialize libpng\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
png_info_ptr = png_create_info_struct(png_ptr);
|
||||||
|
if (!png_info_ptr)
|
||||||
|
{
|
||||||
|
CONS_Debug(DBG_RENDER, "PNG_Load: Error on allocate for libpng\n");
|
||||||
|
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_FAR_KEYWORD
|
||||||
|
if (setjmp(jmpbuf))
|
||||||
|
#else
|
||||||
|
if (setjmp(png_jmpbuf(png_ptr)))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
//CONS_Debug(DBG_RENDER, "libpng load error on %s\n", filename);
|
||||||
|
png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#ifdef USE_FAR_KEYWORD
|
||||||
|
png_memcpy(png_jmpbuf(png_ptr), jmpbuf, sizeof jmp_buf);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// png_source is array which have png data
|
||||||
|
png_io.buffer = (png_bytep)png;
|
||||||
|
png_io.bufsize = size;
|
||||||
|
png_io.current_pos = 0;
|
||||||
|
// set our own read_function
|
||||||
|
png_set_read_fn(png_ptr, &png_io, PNG_IOReader);
|
||||||
|
|
||||||
|
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
|
||||||
|
png_set_user_limits(png_ptr, 2048, 2048);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
png_read_info(png_ptr, png_info_ptr);
|
||||||
|
|
||||||
|
png_get_IHDR(png_ptr, png_info_ptr, &width, &height, &bit_depth, &color_type,
|
||||||
|
NULL, NULL, NULL);
|
||||||
|
|
||||||
|
if (bit_depth == 16)
|
||||||
|
png_set_strip_16(png_ptr);
|
||||||
|
|
||||||
|
if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||||
|
png_set_gray_to_rgb(png_ptr);
|
||||||
|
else if (color_type == PNG_COLOR_TYPE_PALETTE)
|
||||||
|
png_set_palette_to_rgb(png_ptr);
|
||||||
|
|
||||||
|
if (png_get_valid(png_ptr, png_info_ptr, PNG_INFO_tRNS))
|
||||||
|
png_set_tRNS_to_alpha(png_ptr);
|
||||||
|
else if (color_type != PNG_COLOR_TYPE_RGB_ALPHA && color_type != PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||||
|
{
|
||||||
|
#if PNG_LIBPNG_VER < 10207
|
||||||
|
png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER);
|
||||||
|
#else
|
||||||
|
png_set_add_alpha(png_ptr, 0xFF, PNG_FILLER_AFTER);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
png_read_update_info(png_ptr, png_info_ptr);
|
||||||
|
|
||||||
|
// Read the image
|
||||||
|
row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * height);
|
||||||
|
for (y = 0; y < height; y++)
|
||||||
|
row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(png_ptr, png_info_ptr));
|
||||||
|
png_read_image(png_ptr, row_pointers);
|
||||||
|
png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL);
|
||||||
|
|
||||||
|
*w = (INT32)width;
|
||||||
|
*h = (INT32)height;
|
||||||
|
return row_pointers;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert a PNG to a raw image.
|
||||||
|
static UINT8 *PNG_RawConvert(UINT8 *png, UINT16 *w, UINT16 *h, size_t size)
|
||||||
|
{
|
||||||
|
UINT8 *flat;
|
||||||
|
png_uint_32 x, y;
|
||||||
|
png_bytep *row_pointers = PNG_Read(png, w, h, size);
|
||||||
|
png_uint_32 width = *w, height = *h;
|
||||||
|
|
||||||
|
if (!row_pointers)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// Convert the image to 8bpp
|
||||||
|
flat = Z_Malloc(width * height, PU_STATIC, NULL);
|
||||||
|
memset(flat, TRANSPARENTPIXEL, width * height);
|
||||||
|
for (y = 0; y < height; y++)
|
||||||
|
{
|
||||||
|
png_bytep row = row_pointers[y];
|
||||||
|
for (x = 0; x < width; x++)
|
||||||
|
{
|
||||||
|
png_bytep px = &(row[x * 4]);
|
||||||
|
flat[((y * width) + x)] = NearestColor((UINT8)px[0], (UINT8)px[1], (UINT8)px[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(row_pointers);
|
||||||
|
|
||||||
|
return flat;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the alpha mask of the image.
|
||||||
|
static UINT8 *PNG_GetAlphaMask(UINT8 *png, size_t size)
|
||||||
|
{
|
||||||
|
UINT8 *mask;
|
||||||
|
png_uint_32 x, y;
|
||||||
|
UINT16 width, height;
|
||||||
|
png_bytep *row_pointers = PNG_Read(png, &width, &height, size);
|
||||||
|
|
||||||
|
if (!row_pointers)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// Convert the image to 8bpp
|
||||||
|
mask = Z_Malloc(width * height, PU_STATIC, NULL);
|
||||||
|
memset(mask, 0, width * height);
|
||||||
|
for (y = 0; y < height; y++)
|
||||||
|
{
|
||||||
|
png_bytep row = row_pointers[y];
|
||||||
|
for (x = 0; x < width; x++)
|
||||||
|
{
|
||||||
|
png_bytep px = &(row[x * 4]);
|
||||||
|
mask[((y * width) + x)] = (UINT8)px[3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(row_pointers);
|
||||||
|
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert a PNG to a flat.
|
||||||
|
UINT8 *R_PNGToFlat(levelflat_t *levelflat, UINT8 *png, size_t size)
|
||||||
|
{
|
||||||
|
return PNG_RawConvert(png, &levelflat->width, &levelflat->height, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert a PNG to a patch.
|
||||||
|
// This is adapted from the "kartmaker" utility
|
||||||
|
static unsigned char imgbuf[1<<26];
|
||||||
|
patch_t *R_PNGToPatch(UINT8 *png, size_t size)
|
||||||
|
{
|
||||||
|
UINT16 width, height;
|
||||||
|
UINT8 *raw = PNG_RawConvert(png, &width, &height, size);
|
||||||
|
UINT8 *alphamask = PNG_GetAlphaMask(png, size);
|
||||||
|
|
||||||
|
UINT32 x, y;
|
||||||
|
UINT8 *img;
|
||||||
|
UINT8 *imgptr = imgbuf;
|
||||||
|
UINT8 *colpointers, *startofspan;
|
||||||
|
|
||||||
|
#define WRITE8(buf, a) ({*buf = (a); buf++;})
|
||||||
|
#define WRITE16(buf, a) ({*buf = (a)&255; buf++; *buf = (a)>>8; buf++;})
|
||||||
|
#define WRITE32(buf, a) ({WRITE16(buf, (a)&65535); WRITE16(buf, (a)>>16);})
|
||||||
|
|
||||||
|
if (!raw)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// Write image size and offset
|
||||||
|
WRITE16(imgptr, width);
|
||||||
|
WRITE16(imgptr, height);
|
||||||
|
// no offsets
|
||||||
|
WRITE16(imgptr, 0);
|
||||||
|
WRITE16(imgptr, 0);
|
||||||
|
|
||||||
|
// Leave placeholder to column pointers
|
||||||
|
colpointers = imgptr;
|
||||||
|
imgptr += width*4;
|
||||||
|
|
||||||
|
// Write columns
|
||||||
|
for (x = 0; x < width; x++)
|
||||||
|
{
|
||||||
|
int lastStartY = 0;
|
||||||
|
int spanSize = 0;
|
||||||
|
startofspan = NULL;
|
||||||
|
|
||||||
|
//printf("%d ", x);
|
||||||
|
// Write column pointer (@TODO may be wrong)
|
||||||
|
WRITE32(colpointers, imgptr - imgbuf);
|
||||||
|
|
||||||
|
// Write pixels
|
||||||
|
for (y = 0; y < height; y++)
|
||||||
|
{
|
||||||
|
UINT8 paletteIndex = raw[((y * width) + x)];
|
||||||
|
UINT8 opaque = alphamask[((y * width) + x)]; // If 1, we have a pixel
|
||||||
|
|
||||||
|
// End span if we have a transparent pixel
|
||||||
|
if (!opaque)
|
||||||
|
{
|
||||||
|
if (startofspan)
|
||||||
|
WRITE8(imgptr, 0);
|
||||||
|
startofspan = NULL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start new column if we need to
|
||||||
|
if (!startofspan || spanSize == 255)
|
||||||
|
{
|
||||||
|
int writeY = y;
|
||||||
|
|
||||||
|
// If we reached the span size limit, finish the previous span
|
||||||
|
if (startofspan)
|
||||||
|
WRITE8(imgptr, 0);
|
||||||
|
|
||||||
|
if (y > 254)
|
||||||
|
{
|
||||||
|
// Make sure we're aligned to 254
|
||||||
|
if (lastStartY < 254)
|
||||||
|
{
|
||||||
|
WRITE8(imgptr, 254);
|
||||||
|
WRITE8(imgptr, 0);
|
||||||
|
imgptr += 2;
|
||||||
|
lastStartY = 254;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write stopgap empty spans if needed
|
||||||
|
writeY = y - lastStartY;
|
||||||
|
|
||||||
|
while (writeY > 254)
|
||||||
|
{
|
||||||
|
WRITE8(imgptr, 254);
|
||||||
|
WRITE8(imgptr, 0);
|
||||||
|
imgptr += 2;
|
||||||
|
writeY -= 254;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
startofspan = imgptr;
|
||||||
|
WRITE8(imgptr, writeY);///@TODO calculate starting y pos
|
||||||
|
imgptr += 2;
|
||||||
|
spanSize = 0;
|
||||||
|
|
||||||
|
lastStartY = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the pixel
|
||||||
|
WRITE8(imgptr, paletteIndex);
|
||||||
|
spanSize++;
|
||||||
|
startofspan[1] = spanSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startofspan)
|
||||||
|
WRITE8(imgptr, 0);
|
||||||
|
|
||||||
|
WRITE8(imgptr, 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef WRITE8
|
||||||
|
#undef WRITE16
|
||||||
|
#undef WRITE32
|
||||||
|
|
||||||
|
size = imgptr-imgbuf;
|
||||||
|
img = malloc(size);
|
||||||
|
memcpy(img, imgbuf, size);
|
||||||
|
return (patch_t *)img;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean R_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t size)
|
||||||
|
{
|
||||||
|
png_structp png_ptr;
|
||||||
|
png_infop png_info_ptr;
|
||||||
|
png_uint_32 w, h;
|
||||||
|
int bit_depth, color_type;
|
||||||
|
#ifdef PNG_SETJMP_SUPPORTED
|
||||||
|
#ifdef USE_FAR_KEYWORD
|
||||||
|
jmp_buf jmpbuf;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
png_ioread png_io;
|
||||||
|
|
||||||
|
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
|
||||||
|
PNG_error, PNG_warn);
|
||||||
|
if (!png_ptr)
|
||||||
|
{
|
||||||
|
CONS_Debug(DBG_RENDER, "PNG_Load: Error on initialize libpng\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
png_info_ptr = png_create_info_struct(png_ptr);
|
||||||
|
if (!png_info_ptr)
|
||||||
|
{
|
||||||
|
CONS_Debug(DBG_RENDER, "PNG_Load: Error on allocate for libpng\n");
|
||||||
|
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_FAR_KEYWORD
|
||||||
|
if (setjmp(jmpbuf))
|
||||||
|
#else
|
||||||
|
if (setjmp(png_jmpbuf(png_ptr)))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
//CONS_Debug(DBG_RENDER, "libpng load error on %s\n", filename);
|
||||||
|
png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#ifdef USE_FAR_KEYWORD
|
||||||
|
png_memcpy(png_jmpbuf(png_ptr), jmpbuf, sizeof jmp_buf);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// png_source is array which have png data
|
||||||
|
png_io.buffer = (png_bytep)png;
|
||||||
|
png_io.bufsize = size;
|
||||||
|
png_io.current_pos = 0;
|
||||||
|
// set our own read_function
|
||||||
|
png_set_read_fn(png_ptr, &png_io, PNG_IOReader);
|
||||||
|
|
||||||
|
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
|
||||||
|
png_set_user_limits(png_ptr, 2048, 2048);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
png_read_info(png_ptr, png_info_ptr);
|
||||||
|
|
||||||
|
png_get_IHDR(png_ptr, png_info_ptr, &w, &h, &bit_depth, &color_type,
|
||||||
|
NULL, NULL, NULL);
|
||||||
|
|
||||||
|
// okay done. stop.
|
||||||
|
png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL);
|
||||||
|
|
||||||
|
*width = (INT32)w;
|
||||||
|
*height = (INT32)h;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void R_TextureToFlat(size_t tex, UINT8 *flat)
|
||||||
{
|
{
|
||||||
texture_t *texture = textures[tex];
|
texture_t *texture = textures[tex];
|
||||||
|
|
||||||
|
|
|
||||||
14
src/r_data.h
14
src/r_data.h
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#include "r_defs.h"
|
#include "r_defs.h"
|
||||||
#include "r_state.h"
|
#include "r_state.h"
|
||||||
|
#include "p_setup.h" // levelflats
|
||||||
|
|
||||||
#ifdef __GNUG__
|
#ifdef __GNUG__
|
||||||
#pragma interface
|
#pragma interface
|
||||||
|
|
@ -105,14 +106,23 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3);
|
||||||
const char *R_ColormapNameForNum(INT32 num);
|
const char *R_ColormapNameForNum(INT32 num);
|
||||||
|
|
||||||
boolean R_CheckIfPatch(lumpnum_t lump);
|
boolean R_CheckIfPatch(lumpnum_t lump);
|
||||||
|
UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b);
|
||||||
|
|
||||||
void R_FlatPatch(patch_t *patch, UINT8 *flat);
|
void R_PatchToFlat(patch_t *patch, UINT8 *flat);
|
||||||
void R_FlatTexture(size_t tex, UINT8 *flat);
|
void R_TextureToFlat(size_t tex, UINT8 *flat);
|
||||||
void R_CropFlat(UINT8 *srcflat, UINT8 *destflat,
|
void R_CropFlat(UINT8 *srcflat, UINT8 *destflat,
|
||||||
UINT16 srcwidth, UINT16 srcheight,
|
UINT16 srcwidth, UINT16 srcheight,
|
||||||
UINT16 resizewidth, UINT16 resizeheight,
|
UINT16 resizewidth, UINT16 resizeheight,
|
||||||
UINT16 destwidth, UINT16 destheight);
|
UINT16 destwidth, UINT16 destheight);
|
||||||
|
|
||||||
|
#ifndef NO_PNG_LUMPS
|
||||||
|
boolean R_IsLumpPNG(UINT8 *d, size_t s);
|
||||||
|
|
||||||
|
UINT8 *R_PNGToFlat(levelflat_t *levelflat, UINT8 *png, size_t size);
|
||||||
|
patch_t *R_PNGToPatch(UINT8 *png, size_t size);
|
||||||
|
boolean R_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t size);
|
||||||
|
#endif
|
||||||
|
|
||||||
extern INT32 numtextures;
|
extern INT32 numtextures;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -714,7 +714,7 @@ void R_CheckFlatLength(size_t size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture)
|
static void R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture, boolean ispng)
|
||||||
{
|
{
|
||||||
textureflat_t *texflat = &texflats[levelflat->texturenum];
|
textureflat_t *texflat = &texflats[levelflat->texturenum];
|
||||||
patch_t *patch = NULL;
|
patch_t *patch = NULL;
|
||||||
|
|
@ -751,23 +751,46 @@ static void R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture)
|
||||||
|
|
||||||
texflat->flat = Z_Malloc(ds_flatwidth * ds_flatheight, PU_LEVEL, NULL);
|
texflat->flat = Z_Malloc(ds_flatwidth * ds_flatheight, PU_LEVEL, NULL);
|
||||||
memset(texflat->flat, TRANSPARENTPIXEL, ds_flatwidth * ds_flatheight);
|
memset(texflat->flat, TRANSPARENTPIXEL, ds_flatwidth * ds_flatheight);
|
||||||
R_FlatTexture(levelflat->texturenum, texflat->flat);
|
R_TextureToFlat(levelflat->texturenum, texflat->flat);
|
||||||
|
|
||||||
ds_source = texflat->flat;
|
ds_source = texflat->flat;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
patch = (patch_t *)ds_source;
|
patch = (patch_t *)ds_source;
|
||||||
levelflat->width = ds_flatwidth = SHORT(patch->width);
|
#ifndef NO_PNG_LUMPS
|
||||||
levelflat->height = ds_flatheight = SHORT(patch->height);
|
#ifdef HAVE_PNG
|
||||||
|
if (ispng)
|
||||||
|
{
|
||||||
|
levelflat->flatpatch = R_PNGToFlat(levelflat, ds_source, W_LumpLength(levelflat->lumpnum));
|
||||||
|
levelflat->topoffset = levelflat->leftoffset = 0;
|
||||||
|
if (levelflat->flatpatch == NULL)
|
||||||
|
{
|
||||||
|
lumpnum_t redflr = W_CheckNumForName("REDFLR");
|
||||||
|
levelflat->flatpatch = (UINT8 *)W_CacheLumpNum(redflr, PU_STATIC);
|
||||||
|
R_CheckFlatLength(W_LumpLength(redflr));
|
||||||
|
R_CheckPowersOfTwo();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ds_flatwidth = levelflat->width;
|
||||||
|
ds_flatheight = levelflat->height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
levelflat->width = ds_flatwidth = SHORT(patch->width);
|
||||||
|
levelflat->height = ds_flatheight = SHORT(patch->height);
|
||||||
|
|
||||||
levelflat->topoffset = patch->topoffset * FRACUNIT;
|
levelflat->topoffset = patch->topoffset * FRACUNIT;
|
||||||
levelflat->leftoffset = patch->leftoffset * FRACUNIT;
|
levelflat->leftoffset = patch->leftoffset * FRACUNIT;
|
||||||
|
|
||||||
levelflat->flatpatch = Z_Malloc(ds_flatwidth * ds_flatheight, PU_LEVEL, NULL);
|
|
||||||
memset(levelflat->flatpatch, TRANSPARENTPIXEL, ds_flatwidth * ds_flatheight);
|
|
||||||
R_FlatPatch(patch, levelflat->flatpatch);
|
|
||||||
|
|
||||||
|
levelflat->flatpatch = Z_Malloc(ds_flatwidth * ds_flatheight, PU_LEVEL, NULL);
|
||||||
|
memset(levelflat->flatpatch, TRANSPARENTPIXEL, ds_flatwidth * ds_flatheight);
|
||||||
|
R_PatchToFlat(patch, levelflat->flatpatch);
|
||||||
|
}
|
||||||
ds_source = levelflat->flatpatch;
|
ds_source = levelflat->flatpatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1030,19 +1053,20 @@ void R_DrawSinglePlane(visplane_t *pl)
|
||||||
currentplane = pl;
|
currentplane = pl;
|
||||||
levelflat = &levelflats[pl->picnum];
|
levelflat = &levelflats[pl->picnum];
|
||||||
size = W_LumpLength(levelflat->lumpnum);
|
size = W_LumpLength(levelflat->lumpnum);
|
||||||
|
ds_source = (UINT8 *)W_CacheLumpNum(levelflat->lumpnum, PU_STATIC); // Stay here until Z_ChangeTag
|
||||||
|
|
||||||
// Check if the flat is actually a wall texture.
|
// Check if the flat is actually a wall texture.
|
||||||
if (levelflat->texturenum != 0 && levelflat->texturenum != -1)
|
if (levelflat->texturenum != 0 && levelflat->texturenum != -1)
|
||||||
R_GetPatchFlat(levelflat, true);
|
R_GetPatchFlat(levelflat, true, false);
|
||||||
// Maybe it's just a patch, then?
|
// Maybe it's just a patch, then?
|
||||||
else if (R_CheckIfPatch(levelflat->lumpnum))
|
else if (R_CheckIfPatch(levelflat->lumpnum))
|
||||||
R_GetPatchFlat(levelflat, false);
|
R_GetPatchFlat(levelflat, false, false);
|
||||||
|
// Maybe it's a PNG?!
|
||||||
|
else if (R_IsLumpPNG(ds_source, size))
|
||||||
|
R_GetPatchFlat(levelflat, false, true);
|
||||||
// It's a raw flat.
|
// It's a raw flat.
|
||||||
else
|
else
|
||||||
{
|
|
||||||
ds_source = (UINT8 *)W_CacheLumpNum(levelflat->lumpnum, PU_STATIC); // Stay here until Z_ChangeTag
|
|
||||||
R_CheckFlatLength(size);
|
R_CheckFlatLength(size);
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the flat has dimensions that are powers-of-two numbers.
|
// Check if the flat has dimensions that are powers-of-two numbers.
|
||||||
if (R_CheckPowersOfTwo())
|
if (R_CheckPowersOfTwo())
|
||||||
|
|
|
||||||
|
|
@ -1179,8 +1179,6 @@ void zerr(int ret)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define NO_PNG_LUMPS
|
|
||||||
|
|
||||||
#ifdef NO_PNG_LUMPS
|
#ifdef NO_PNG_LUMPS
|
||||||
static void ErrorIfPNG(UINT8 *d, size_t s, char *f, char *l)
|
static void ErrorIfPNG(UINT8 *d, size_t s, char *f, char *l)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue