Read user chunks
This commit is contained in:
parent
affff0a7e5
commit
a5ff609873
|
@ -62,7 +62,6 @@
|
||||||
|
|
||||||
#define PNG_NO_READ_iTXt
|
#define PNG_NO_READ_iTXt
|
||||||
#define PNG_NO_READ_APNG
|
#define PNG_NO_READ_APNG
|
||||||
#define PNG_NO_READ_UNKNOWN_CHUNKS
|
|
||||||
#define PNG_NO_READ_USER_TRANSFORM
|
#define PNG_NO_READ_USER_TRANSFORM
|
||||||
#define PNG_READ_BGR_SUPPORTED
|
#define PNG_READ_BGR_SUPPORTED
|
||||||
#define PNG_NO_READ_SWAP_ALPHA
|
#define PNG_NO_READ_SWAP_ALPHA
|
||||||
|
|
Binary file not shown.
Binary file not shown.
91
src/r_data.c
91
src/r_data.c
|
@ -2603,17 +2603,40 @@ typedef struct {
|
||||||
png_bytep buffer;
|
png_bytep buffer;
|
||||||
png_uint_32 bufsize;
|
png_uint_32 bufsize;
|
||||||
png_uint_32 current_pos;
|
png_uint_32 current_pos;
|
||||||
} png_ioread;
|
} png_io_t;
|
||||||
|
|
||||||
static void PNG_IOReader(png_structp png_ptr, png_bytep data, png_size_t length)
|
static void PNG_IOReader(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||||
{
|
{
|
||||||
png_ioread *f = png_get_io_ptr(png_ptr);
|
png_io_t *f = png_get_io_ptr(png_ptr);
|
||||||
if (length > (f->bufsize - f->current_pos))
|
if (length > (f->bufsize - f->current_pos))
|
||||||
png_error(png_ptr, "PNG_IOReader: buffer overrun");
|
png_error(png_ptr, "PNG_IOReader: buffer overrun");
|
||||||
memcpy(data, f->buffer + f->current_pos, length);
|
memcpy(data, f->buffer + f->current_pos, length);
|
||||||
f->current_pos += length;
|
f->current_pos += length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char name[4];
|
||||||
|
void *data;
|
||||||
|
size_t size;
|
||||||
|
} png_chunk_t;
|
||||||
|
|
||||||
|
static png_byte *chunkname = NULL;
|
||||||
|
static png_chunk_t chunk;
|
||||||
|
|
||||||
|
static int PNG_ChunkReader(png_structp png_ptr, png_unknown_chunkp chonk)
|
||||||
|
{
|
||||||
|
if (!memcmp(chonk->name, chunkname, 4))
|
||||||
|
{
|
||||||
|
memcpy(chunk.name, chonk->name, 4);
|
||||||
|
chunk.size = chonk->size;
|
||||||
|
chunk.data = Z_Malloc(chunk.size, PU_STATIC, NULL);
|
||||||
|
memcpy(chunk.data, chonk->data, chunk.size);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void PNG_error(png_structp PNG, png_const_charp pngtext)
|
static void PNG_error(png_structp PNG, png_const_charp pngtext)
|
||||||
{
|
{
|
||||||
CONS_Debug(DBG_RENDER, "libpng error at %p: %s", PNG, pngtext);
|
CONS_Debug(DBG_RENDER, "libpng error at %p: %s", PNG, pngtext);
|
||||||
|
@ -2638,11 +2661,13 @@ static png_bytep *PNG_Read(UINT8 *png, UINT16 *w, UINT16 *h, INT16 *topoffset, I
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
png_ioread png_io;
|
png_io_t png_io;
|
||||||
png_bytep *row_pointers;
|
png_bytep *row_pointers;
|
||||||
|
|
||||||
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
|
png_byte grAb_chunk[5] = {'g', 'r', 'A', 'b', (png_byte)'\0'};
|
||||||
PNG_error, PNG_warn);
|
png_voidp *user_chunk_ptr;
|
||||||
|
|
||||||
|
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, PNG_error, PNG_warn);
|
||||||
if (!png_ptr)
|
if (!png_ptr)
|
||||||
{
|
{
|
||||||
CONS_Debug(DBG_RENDER, "PNG_Load: Error on initialize libpng\n");
|
CONS_Debug(DBG_RENDER, "PNG_Load: Error on initialize libpng\n");
|
||||||
|
@ -2677,12 +2702,18 @@ static png_bytep *PNG_Read(UINT8 *png, UINT16 *w, UINT16 *h, INT16 *topoffset, I
|
||||||
png_io.current_pos = 0;
|
png_io.current_pos = 0;
|
||||||
png_set_read_fn(png_ptr, &png_io, PNG_IOReader);
|
png_set_read_fn(png_ptr, &png_io, PNG_IOReader);
|
||||||
|
|
||||||
|
memset(&chunk, 0x00, sizeof(png_chunk_t));
|
||||||
|
chunkname = grAb_chunk; // I want to read a grAb chunk
|
||||||
|
|
||||||
|
user_chunk_ptr = png_get_user_chunk_ptr(png_ptr);
|
||||||
|
png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr, PNG_ChunkReader);
|
||||||
|
png_set_keep_unknown_chunks(png_ptr, 2, chunkname, 1);
|
||||||
|
|
||||||
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
|
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
|
||||||
png_set_user_limits(png_ptr, 2048, 2048);
|
png_set_user_limits(png_ptr, 2048, 2048);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
png_read_info(png_ptr, png_info_ptr);
|
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);
|
png_get_IHDR(png_ptr, png_info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);
|
||||||
|
|
||||||
if (bit_depth == 16)
|
if (bit_depth == 16)
|
||||||
|
@ -2715,35 +2746,31 @@ static png_bytep *PNG_Read(UINT8 *png, UINT16 *w, UINT16 *h, INT16 *topoffset, I
|
||||||
// Read grAB chunk
|
// Read grAB chunk
|
||||||
if (topoffset || leftoffset)
|
if (topoffset || leftoffset)
|
||||||
{
|
{
|
||||||
UINT8 *header = png;
|
INT32 *offsets = (INT32 *)chunk.data;
|
||||||
while (size--)
|
|
||||||
{
|
// The grAb chunk stores offsets as big-endian numbers.
|
||||||
if (!memcmp(header, "grAb", 4))
|
#ifdef SRB2_BIG_ENDIAN
|
||||||
{
|
#define ENDIANESS(x) (x)
|
||||||
// The grAb chunk stores offsets as big-endian numbers.
|
#else
|
||||||
#ifdef SRB2_BIG_ENDIAN
|
#define ENDIANESS(x) ((x>>24)&0xff)|((x<<8)&0xff0000)|((x>>8)&0xff00)|((x<<24)&0xff000000)
|
||||||
#define ENDIANESS(x) (x)
|
#endif
|
||||||
#else
|
|
||||||
#define ENDIANESS(x) ((x>>24)&0xff)|((x<<8)&0xff0000)|((x>>8)&0xff00)|((x<<24)&0xff000000)
|
// read left offset
|
||||||
#endif
|
if (leftoffset != NULL)
|
||||||
// skip name
|
*leftoffset = (INT16)ENDIANESS(*offsets);
|
||||||
header += 4;
|
offsets++;
|
||||||
// read left offset
|
|
||||||
if (leftoffset != NULL)
|
// read top offset
|
||||||
*leftoffset = (INT16)ENDIANESS(*(INT32 *)header);
|
if (topoffset != NULL)
|
||||||
// read top offset
|
*topoffset = (INT16)ENDIANESS(*offsets);
|
||||||
header += 4;
|
|
||||||
if (topoffset != NULL)
|
#undef ENDIANESS
|
||||||
*topoffset = (INT16)ENDIANESS(*(INT32 *)header);
|
|
||||||
#undef ENDIANESS
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
header++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// bye
|
// bye
|
||||||
png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL);
|
png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL);
|
||||||
|
if (chunk.data)
|
||||||
|
Z_Free(chunk.data);
|
||||||
|
|
||||||
*w = (INT32)width;
|
*w = (INT32)width;
|
||||||
*h = (INT32)height;
|
*h = (INT32)height;
|
||||||
|
@ -2920,7 +2947,7 @@ boolean R_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t size)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
png_ioread png_io;
|
png_io_t png_io;
|
||||||
|
|
||||||
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
|
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
|
||||||
PNG_error, PNG_warn);
|
PNG_error, PNG_warn);
|
||||||
|
|
Loading…
Reference in New Issue