mirror of https://github.com/FWGS/xash3d-fwgs
engine: imagelib: add 16-bit PNG load support
This commit is contained in:
parent
f045103abb
commit
f16641b606
|
@ -40,9 +40,9 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
short p, a, b, c, pa, pb, pc;
|
short p, a, b, c, pa, pb, pc;
|
||||||
byte *buf_p, *pixbuf, *raw, *prior, *idat_buf = NULL, *uncompressed_buffer = NULL, *rowend;
|
byte *buf_p, *pixbuf, *raw, *prior, *idat_buf = NULL, *uncompressed_buffer = NULL;
|
||||||
uint chunk_len, crc32, crc32_check, oldsize = 0, newsize = 0, rowsize;
|
uint chunk_len, crc32, crc32_check, oldsize = 0, newsize = 0, rowsize;
|
||||||
uint uncompressed_size, pixel_size, i, y, filter_type, chunk_sign;
|
uint uncompressed_size, pixel_size, i, y, filter_type, chunk_sign, channel_size;
|
||||||
qboolean has_iend_chunk = false;
|
qboolean has_iend_chunk = false;
|
||||||
z_stream stream = {0};
|
z_stream stream = {0};
|
||||||
png_t png_hdr;
|
png_t png_hdr;
|
||||||
|
@ -89,9 +89,9 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( png_hdr.ihdr_chunk.bitdepth != 8 )
|
if( png_hdr.ihdr_chunk.bitdepth != 8 && png_hdr.ihdr_chunk.bitdepth != 16 )
|
||||||
{
|
{
|
||||||
Con_DPrintf( S_WARN "Image_LoadPNG: Only 8-bit images is supported (%s)\n", name );
|
Con_DPrintf( S_WARN "Image_LoadPNG: Only 8-bit or 16-bit images is supported (%s)\n", name );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,10 +228,19 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
image.type = PF_RGBA_32; // always exctracted to 32-bit buffer
|
if( png_hdr.ihdr_chunk.bitdepth == 8 )
|
||||||
|
{
|
||||||
|
image.type = PF_RGBA_32; // always exctracted to 32-bit buffer
|
||||||
|
channel_size = 1;
|
||||||
|
}
|
||||||
|
else // if( png_hdr.ihdr_chunk.bitdepth == 16 )
|
||||||
|
{
|
||||||
|
image.type = PF_RGBA_64;
|
||||||
|
channel_size = 2;
|
||||||
|
}
|
||||||
image.width = png_hdr.ihdr_chunk.width;
|
image.width = png_hdr.ihdr_chunk.width;
|
||||||
image.height = png_hdr.ihdr_chunk.height;
|
image.height = png_hdr.ihdr_chunk.height;
|
||||||
image.size = image.height * image.width * 4;
|
image.size = image.height * image.width * channel_size * 4;
|
||||||
image.flags |= IMAGE_HAS_COLOR;
|
image.flags |= IMAGE_HAS_COLOR;
|
||||||
|
|
||||||
if( png_hdr.ihdr_chunk.colortype == PNG_CT_RGBA )
|
if( png_hdr.ihdr_chunk.colortype == PNG_CT_RGBA )
|
||||||
|
@ -241,7 +250,7 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
|
||||||
|
|
||||||
rowsize = pixel_size * image.width;
|
rowsize = pixel_size * image.width;
|
||||||
|
|
||||||
uncompressed_size = image.height * ( rowsize + 1 ); // +1 for filter
|
uncompressed_size = image.height * ( rowsize * channel_size + 1 ); // +1 for filter
|
||||||
uncompressed_buffer = Mem_Malloc( host.imagepool, uncompressed_size );
|
uncompressed_buffer = Mem_Malloc( host.imagepool, uncompressed_size );
|
||||||
|
|
||||||
stream.next_in = idat_buf;
|
stream.next_in = idat_buf;
|
||||||
|
@ -279,6 +288,9 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
|
||||||
if( png_hdr.ihdr_chunk.colortype == PNG_CT_RGB )
|
if( png_hdr.ihdr_chunk.colortype == PNG_CT_RGB )
|
||||||
prior = pixbuf = raw;
|
prior = pixbuf = raw;
|
||||||
|
|
||||||
|
rowsize *= channel_size;
|
||||||
|
pixel_size *= channel_size;
|
||||||
|
|
||||||
filter_type = *raw++;
|
filter_type = *raw++;
|
||||||
|
|
||||||
// decode adaptive filter
|
// decode adaptive filter
|
||||||
|
@ -384,19 +396,38 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
|
||||||
pixbuf = image.rgba;
|
pixbuf = image.rgba;
|
||||||
raw = uncompressed_buffer;
|
raw = uncompressed_buffer;
|
||||||
|
|
||||||
for( y = 0; y < image.height; y++ )
|
for( y = 0; y < image.height * image.width; y++, raw += pixel_size )
|
||||||
{
|
{
|
||||||
rowend = raw + rowsize;
|
*pixbuf++ = raw[0];
|
||||||
for( ; raw < rowend; raw += pixel_size )
|
*pixbuf++ = raw[1];
|
||||||
|
*pixbuf++ = raw[2];
|
||||||
|
if( channel_size == 1 )
|
||||||
{
|
{
|
||||||
*pixbuf++ = raw[0];
|
*pixbuf++ = 0xFF;
|
||||||
*pixbuf++ = raw[1];
|
}
|
||||||
*pixbuf++ = raw[2];
|
else
|
||||||
|
{
|
||||||
|
*pixbuf++ = raw[3];
|
||||||
|
*pixbuf++ = raw[4];
|
||||||
|
*pixbuf++ = raw[5];
|
||||||
|
*pixbuf++ = 0xFF;
|
||||||
*pixbuf++ = 0xFF;
|
*pixbuf++ = 0xFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if XASH_LITTLE_ENDIAN
|
||||||
|
if( channel_size == 2 )
|
||||||
|
{
|
||||||
|
pixbuf = image.rgba;
|
||||||
|
for( y = 0; y < image.height * image.width * 4; y++, pixbuf += 2 )
|
||||||
|
{
|
||||||
|
uint16_t val = *(uint16_t*)pixbuf;
|
||||||
|
*(uint16_t*)pixbuf = ntohs( val );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* XASH_LITTLE_ENDIAN */
|
||||||
|
|
||||||
Mem_Free( uncompressed_buffer );
|
Mem_Free( uncompressed_buffer );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Reference in New Issue