mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-01-19 07:51:43 +00:00
PNG support
This commit is contained in:
parent
0bcf89679e
commit
39857a846a
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+
|
||||
#define NEWCLIP
|
||||
|
||||
//#define NO_PNG_LUMPS
|
||||
|
||||
#endif // __DOOMDEF__
|
||||
|
|
|
@ -451,7 +451,10 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex)
|
|||
// Composite the columns together.
|
||||
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);
|
||||
if (R_IsLumpPNG((UINT8 *)realpatch, lumplength))
|
||||
realpatch = R_PNGToPatch((UINT8 *)realpatch, lumplength);
|
||||
HWR_DrawPatchInCache(&grtex->mipmap,
|
||||
blockwidth, blockheight,
|
||||
blockwidth*format2bpp[grtex->mipmap.grInfo.format],
|
||||
|
@ -683,11 +686,14 @@ lumpnum_t gr_patchflat;
|
|||
static void HWR_LoadPatchFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum)
|
||||
{
|
||||
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->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)
|
||||
|
@ -777,7 +783,7 @@ static void HWR_LoadTextureFlat(GLMipmap_t *grMipmap, INT32 texturenum)
|
|||
grMipmap->width = (UINT16)textures[texturenum]->width;
|
||||
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)
|
||||
|
|
459
src/r_data.c
459
src/r_data.c
|
@ -40,6 +40,28 @@
|
|||
#include <errno.h>
|
||||
#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.
|
||||
// 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'
|
||||
// Build the full textures from patches.
|
||||
// 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
|
||||
// per level, when enough memory is available.
|
||||
|
@ -195,6 +217,10 @@ static UINT8 *R_GenerateTexture(size_t texnum)
|
|||
column_t *patchcol;
|
||||
UINT32 *colofs;
|
||||
|
||||
UINT16 wadnum;
|
||||
lumpnum_t lumpnum;
|
||||
size_t lumplength;
|
||||
|
||||
I_Assert(texnum <= (size_t)numtextures);
|
||||
texture = textures[texnum];
|
||||
I_Assert(texture != NULL);
|
||||
|
@ -209,7 +235,13 @@ static UINT8 *R_GenerateTexture(size_t texnum)
|
|||
{
|
||||
boolean holey = false;
|
||||
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.
|
||||
if (texture->width > SHORT(realpatch->width) || texture->height > SHORT(realpatch->height))
|
||||
|
@ -238,7 +270,7 @@ static UINT8 *R_GenerateTexture(size_t texnum)
|
|||
if (holey)
|
||||
{
|
||||
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
|
||||
&texturecache[texnum]);
|
||||
M_Memcpy(block, realpatch, blocksize);
|
||||
|
@ -274,7 +306,13 @@ static UINT8 *R_GenerateTexture(size_t texnum)
|
|||
// Composite the columns together.
|
||||
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;
|
||||
x2 = x1 + SHORT(realpatch->width);
|
||||
|
||||
|
@ -487,7 +525,10 @@ void R_LoadTextures(void)
|
|||
// Work through each lump between the markers in the WAD.
|
||||
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,
|
||||
// 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);
|
||||
|
||||
// Set texture properties.
|
||||
M_Memcpy(texture->name, W_CheckNameForNumPwad((UINT16)w, texstart + j), sizeof(texture->name));
|
||||
texture->width = SHORT(patchlump->width);
|
||||
texture->height = SHORT(patchlump->height);
|
||||
M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name));
|
||||
if (R_IsLumpPNG((UINT8 *)patchlump, lumplength))
|
||||
{
|
||||
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->holes = false;
|
||||
|
||||
|
@ -1178,7 +1229,6 @@ INT32 R_ColormapNumForName(char *name)
|
|||
//
|
||||
static double deltas[256][3], map[256][3];
|
||||
|
||||
static UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b);
|
||||
static int RoundUp(double number);
|
||||
|
||||
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!
|
||||
// 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 distortion, bestdistortion = 256 * 256 * 4, bestcolor = 0, i;
|
||||
|
@ -1686,7 +1736,7 @@ boolean R_CheckIfPatch(lumpnum_t lump)
|
|||
return result;
|
||||
}
|
||||
|
||||
void R_FlatPatch(patch_t *patch, UINT8 *flat)
|
||||
void R_PatchToFlat(patch_t *patch, UINT8 *flat)
|
||||
{
|
||||
fixed_t col, ofs;
|
||||
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];
|
||||
|
||||
|
|
14
src/r_data.h
14
src/r_data.h
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "r_defs.h"
|
||||
#include "r_state.h"
|
||||
#include "p_setup.h" // levelflats
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface
|
||||
|
@ -105,14 +106,23 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3);
|
|||
const char *R_ColormapNameForNum(INT32 num);
|
||||
|
||||
boolean R_CheckIfPatch(lumpnum_t lump);
|
||||
UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b);
|
||||
|
||||
void R_FlatPatch(patch_t *patch, UINT8 *flat);
|
||||
void R_FlatTexture(size_t tex, UINT8 *flat);
|
||||
void R_PatchToFlat(patch_t *patch, UINT8 *flat);
|
||||
void R_TextureToFlat(size_t tex, UINT8 *flat);
|
||||
void R_CropFlat(UINT8 *srcflat, UINT8 *destflat,
|
||||
UINT16 srcwidth, UINT16 srcheight,
|
||||
UINT16 resizewidth, UINT16 resizeheight,
|
||||
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;
|
||||
|
||||
#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];
|
||||
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);
|
||||
memset(texflat->flat, TRANSPARENTPIXEL, ds_flatwidth * ds_flatheight);
|
||||
R_FlatTexture(levelflat->texturenum, texflat->flat);
|
||||
R_TextureToFlat(levelflat->texturenum, texflat->flat);
|
||||
|
||||
ds_source = texflat->flat;
|
||||
}
|
||||
else
|
||||
{
|
||||
patch = (patch_t *)ds_source;
|
||||
levelflat->width = ds_flatwidth = SHORT(patch->width);
|
||||
levelflat->height = ds_flatheight = SHORT(patch->height);
|
||||
#ifndef NO_PNG_LUMPS
|
||||
#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->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->topoffset = patch->topoffset * 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_PatchToFlat(patch, levelflat->flatpatch);
|
||||
}
|
||||
ds_source = levelflat->flatpatch;
|
||||
}
|
||||
|
||||
|
@ -1030,19 +1053,20 @@ void R_DrawSinglePlane(visplane_t *pl)
|
|||
currentplane = pl;
|
||||
levelflat = &levelflats[pl->picnum];
|
||||
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.
|
||||
if (levelflat->texturenum != 0 && levelflat->texturenum != -1)
|
||||
R_GetPatchFlat(levelflat, true);
|
||||
R_GetPatchFlat(levelflat, true, false);
|
||||
// Maybe it's just a patch, then?
|
||||
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.
|
||||
else
|
||||
{
|
||||
ds_source = (UINT8 *)W_CacheLumpNum(levelflat->lumpnum, PU_STATIC); // Stay here until Z_ChangeTag
|
||||
R_CheckFlatLength(size);
|
||||
}
|
||||
|
||||
// Check if the flat has dimensions that are powers-of-two numbers.
|
||||
if (R_CheckPowersOfTwo())
|
||||
|
|
|
@ -1179,8 +1179,6 @@ void zerr(int ret)
|
|||
}
|
||||
#endif
|
||||
|
||||
#define NO_PNG_LUMPS
|
||||
|
||||
#ifdef NO_PNG_LUMPS
|
||||
static void ErrorIfPNG(UINT8 *d, size_t s, char *f, char *l)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue