mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-01-29 20:50:58 +00:00
Attempt to use the PNG image's palette, if it is present
This commit is contained in:
parent
4e437076c1
commit
0750d273a6
1 changed files with 163 additions and 30 deletions
|
@ -798,13 +798,24 @@ 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(const UINT8 *png, INT32 *w, INT32 *h, INT16 *topoffset, INT16 *leftoffset, size_t size)
|
||||
static png_bytep *PNG_Read(
|
||||
const UINT8 *png,
|
||||
INT32 *w, INT32 *h, INT16 *topoffset, INT16 *leftoffset,
|
||||
boolean *use_palette, 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;
|
||||
|
||||
png_colorp palette;
|
||||
int palette_size;
|
||||
|
||||
png_bytep trans;
|
||||
int trans_num;
|
||||
png_color_16p trans_values;
|
||||
|
||||
#ifdef PNG_SETJMP_SUPPORTED
|
||||
#ifdef USE_FAR_KEYWORD
|
||||
jmp_buf jmpbuf;
|
||||
|
@ -864,10 +875,48 @@ static png_bytep *PNG_Read(const UINT8 *png, INT32 *w, INT32 *h, INT16 *topoffse
|
|||
if (bit_depth == 16)
|
||||
png_set_strip_16(png_ptr);
|
||||
|
||||
palette = NULL;
|
||||
*use_palette = false;
|
||||
|
||||
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);
|
||||
{
|
||||
boolean usepal = false;
|
||||
|
||||
// Lactozilla: Check if the PNG has a palette, and if its color count
|
||||
// matches the color count of SRB2's palette: 256 colors.
|
||||
if (png_get_PLTE(png_ptr, png_info_ptr, &palette, &palette_size))
|
||||
{
|
||||
if (palette_size == 256)
|
||||
usepal = true;
|
||||
}
|
||||
|
||||
// If any of the tRNS colors have an alpha lower than 0xFF, and that
|
||||
// color is present on the image, the palette flag is disabled.
|
||||
png_get_tRNS(png_ptr, png_info_ptr, &trans, &trans_num, &trans_values);
|
||||
|
||||
if (trans_num == 256)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < trans_num; i++)
|
||||
{
|
||||
// libpng will transform this image into RGB even if
|
||||
// the transparent index does not exist in the image,
|
||||
// and there is no way around that.
|
||||
if (trans[i] < 0xFF)
|
||||
{
|
||||
usepal = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (usepal)
|
||||
*use_palette = true;
|
||||
else
|
||||
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);
|
||||
|
@ -908,6 +957,7 @@ static png_bytep *PNG_Read(const UINT8 *png, INT32 *w, INT32 *h, INT16 *topoffse
|
|||
|
||||
*w = (INT32)width;
|
||||
*h = (INT32)height;
|
||||
|
||||
return row_pointers;
|
||||
}
|
||||
|
||||
|
@ -935,12 +985,17 @@ void *Picture_PNGConvert(
|
|||
INT32 outbpp;
|
||||
size_t flatsize;
|
||||
png_uint_32 x, y;
|
||||
png_bytep *row_pointers = PNG_Read(png, w, h, topoffset, leftoffset, insize);
|
||||
png_bytep row;
|
||||
boolean palette = false;
|
||||
png_bytep *row_pointers = PNG_Read(png, w, h, topoffset, leftoffset, &palette, insize);
|
||||
png_uint_32 width = *w, height = *h;
|
||||
|
||||
if (png == NULL)
|
||||
I_Error("Picture_PNGConvert: picture was NULL!");
|
||||
|
||||
if (row_pointers == NULL)
|
||||
I_Error("Picture_PNGConvert: row_pointers was NULL!");
|
||||
|
||||
// Find the output format's bits per pixel amount
|
||||
outbpp = Picture_FormatBPP(outformat);
|
||||
|
||||
|
@ -973,43 +1028,119 @@ void *Picture_PNGConvert(
|
|||
InitColorLUT(&png_colorlookup, pMasterPalette, false);
|
||||
#endif
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
if (outbpp == PICDEPTH_32BPP)
|
||||
{
|
||||
png_bytep row = row_pointers[y];
|
||||
for (x = 0; x < width; x++)
|
||||
RGBA_t out;
|
||||
UINT32 *outflat = (UINT32 *)flat;
|
||||
|
||||
if (palette)
|
||||
{
|
||||
png_bytep px = &(row[x * 4]);
|
||||
if ((UINT8)px[3])
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
UINT8 red = (UINT8)px[0];
|
||||
UINT8 green = (UINT8)px[1];
|
||||
UINT8 blue = (UINT8)px[2];
|
||||
UINT8 alpha = (UINT8)px[3];
|
||||
if (outbpp == PICDEPTH_32BPP)
|
||||
row = row_pointers[y];
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
UINT32 *outflat = (UINT32 *)flat;
|
||||
RGBA_t out;
|
||||
out.s.red = red;
|
||||
out.s.green = green;
|
||||
out.s.blue = blue;
|
||||
out.s.alpha = alpha;
|
||||
out = V_GetColor(row[x]);
|
||||
outflat[((y * width) + x)] = out.rgba;
|
||||
}
|
||||
else
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
row = row_pointers[y];
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
#ifdef PICTURE_PNG_USELOOKUP
|
||||
UINT8 palidx = GetColorLUT(&png_colorlookup, red, green, blue);
|
||||
#else
|
||||
UINT8 palidx = NearestColor(red, green, blue);
|
||||
#endif
|
||||
if (outbpp == PICDEPTH_16BPP)
|
||||
png_bytep px = &(row[x * 4]);
|
||||
if ((UINT8)px[3])
|
||||
{
|
||||
UINT16 *outflat = (UINT16 *)flat;
|
||||
outflat[((y * width) + x)] = (alpha << 8) | palidx;
|
||||
out.s.red = (UINT8)px[0];
|
||||
out.s.green = (UINT8)px[1];
|
||||
out.s.blue = (UINT8)px[2];
|
||||
out.s.alpha = (UINT8)px[3];
|
||||
outflat[((y * width) + x)] = out.rgba;
|
||||
}
|
||||
else // 8bpp
|
||||
else
|
||||
outflat[((y * width) + x)] = 0x00000000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (outbpp == PICDEPTH_16BPP)
|
||||
{
|
||||
UINT16 *outflat = (UINT16 *)flat;
|
||||
|
||||
if (palette)
|
||||
{
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
row = row_pointers[y];
|
||||
for (x = 0; x < width; x++)
|
||||
outflat[((y * width) + x)] = (0xFF << 8) | row[x];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
row = row_pointers[y];
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
png_bytep px = &(row[x * 4]);
|
||||
UINT8 red = (UINT8)px[0];
|
||||
UINT8 green = (UINT8)px[1];
|
||||
UINT8 blue = (UINT8)px[2];
|
||||
UINT8 alpha = (UINT8)px[3];
|
||||
|
||||
if (alpha)
|
||||
{
|
||||
UINT8 *outflat = (UINT8 *)flat;
|
||||
#ifdef PICTURE_PNG_USELOOKUP
|
||||
UINT8 palidx = GetColorLUT(&png_colorlookup, red, green, blue);
|
||||
#else
|
||||
UINT8 palidx = NearestColor(red, green, blue);
|
||||
#endif
|
||||
outflat[((y * width) + x)] = (0xFF << 8) | palidx;
|
||||
}
|
||||
else
|
||||
outflat[((y * width) + x)] = 0x0000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else // 8bpp
|
||||
{
|
||||
UINT8 *outflat = (UINT8 *)flat;
|
||||
|
||||
if (palette)
|
||||
{
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
row = row_pointers[y];
|
||||
for (x = 0; x < width; x++)
|
||||
outflat[((y * width) + x)] = row[x];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
row = row_pointers[y];
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
png_bytep px = &(row[x * 4]);
|
||||
UINT8 red = (UINT8)px[0];
|
||||
UINT8 green = (UINT8)px[1];
|
||||
UINT8 blue = (UINT8)px[2];
|
||||
UINT8 alpha = (UINT8)px[3];
|
||||
|
||||
if (alpha)
|
||||
{
|
||||
#ifdef PICTURE_PNG_USELOOKUP
|
||||
UINT8 palidx = GetColorLUT(&png_colorlookup, red, green, blue);
|
||||
#else
|
||||
UINT8 palidx = NearestColor(red, green, blue);
|
||||
#endif
|
||||
outflat[((y * width) + x)] = palidx;
|
||||
}
|
||||
}
|
||||
|
@ -1018,6 +1149,8 @@ void *Picture_PNGConvert(
|
|||
}
|
||||
|
||||
// Free the row pointers that we allocated for libpng.
|
||||
for (y = 0; y < height; y++)
|
||||
free(row_pointers[y]);
|
||||
free(row_pointers);
|
||||
|
||||
// But wait, there's more!
|
||||
|
|
Loading…
Reference in a new issue