mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-12-03 17:32:26 +00:00
- moved some palette related code into the 'common' folder.
This commit is contained in:
parent
c713850dac
commit
05239c63f9
5 changed files with 162 additions and 159 deletions
|
@ -268,7 +268,7 @@ if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
|
||||||
set( CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -pg" )
|
set( CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -pg" )
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set( REL_CXX_FLAGS "-fno-rtti" )
|
#set( REL_CXX_FLAGS "-fno-rtti" )
|
||||||
if( NOT PROFILE AND NOT APPLE )
|
if( NOT PROFILE AND NOT APPLE )
|
||||||
# On OS X frame pointers are required for exception handling, at least with Clang
|
# On OS X frame pointers are required for exception handling, at least with Clang
|
||||||
set( REL_CXX_FLAGS "${REL_CXX_FLAGS} -fomit-frame-pointer" )
|
set( REL_CXX_FLAGS "${REL_CXX_FLAGS} -fomit-frame-pointer" )
|
||||||
|
|
|
@ -32,8 +32,10 @@
|
||||||
**
|
**
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include "palutil.h"
|
#include "palutil.h"
|
||||||
#include "palentry.h"
|
#include "palentry.h"
|
||||||
|
#include "sc_man.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
|
|
||||||
/****************************/
|
/****************************/
|
||||||
|
@ -313,3 +315,155 @@ void HSVtoRGB (float *r, float *g, float *b, float h, float s, float v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sortforremap(const void* a, const void* b)
|
||||||
|
{
|
||||||
|
return (*(const uint32_t*)a & 0xFFFFFF) - (*(const uint32_t*)b & 0xFFFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sortforremap2(const void* a, const void* b)
|
||||||
|
{
|
||||||
|
const RemappingWork* ap = (const RemappingWork*)a;
|
||||||
|
const RemappingWork* bp = (const RemappingWork*)b;
|
||||||
|
|
||||||
|
if (ap->Color == bp->Color)
|
||||||
|
{
|
||||||
|
return bp->Foreign - ap->Foreign;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ap->Color - bp->Color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct RemappingWork
|
||||||
|
{
|
||||||
|
uint32_t Color;
|
||||||
|
uint8_t Foreign; // 0 = local palette, 1 = foreign palette
|
||||||
|
uint8_t PalEntry; // Entry # in the palette
|
||||||
|
uint8_t Pad[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
void MakeRemap(uint32_t* BaseColors, const uint32_t* colors, uint8_t* remap, const uint8_t* useful, int numcolors)
|
||||||
|
{
|
||||||
|
RemappingWork workspace[255 + 256];
|
||||||
|
int i, j, k;
|
||||||
|
|
||||||
|
// Fill in workspace with the colors from the passed palette and this palette.
|
||||||
|
// By sorting this array, we can quickly find exact matches so that we can
|
||||||
|
// minimize the time spent calling BestColor for near matches.
|
||||||
|
|
||||||
|
for (i = 1; i < 256; ++i)
|
||||||
|
{
|
||||||
|
workspace[i - 1].Color = uint32_t(BaseColors[i]) & 0xFFFFFF;
|
||||||
|
workspace[i - 1].Foreign = 0;
|
||||||
|
workspace[i - 1].PalEntry = i;
|
||||||
|
}
|
||||||
|
for (i = k = 0, j = 255; i < numcolors; ++i)
|
||||||
|
{
|
||||||
|
if (useful == NULL || useful[i] != 0)
|
||||||
|
{
|
||||||
|
workspace[j].Color = colors[i] & 0xFFFFFF;
|
||||||
|
workspace[j].Foreign = 1;
|
||||||
|
workspace[j].PalEntry = i;
|
||||||
|
++j;
|
||||||
|
++k;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
remap[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
qsort(workspace, j, sizeof(RemappingWork), sortforremap2);
|
||||||
|
|
||||||
|
// Find exact matches
|
||||||
|
--j;
|
||||||
|
for (i = 0; i < j; ++i)
|
||||||
|
{
|
||||||
|
if (workspace[i].Foreign)
|
||||||
|
{
|
||||||
|
if (!workspace[i + 1].Foreign && workspace[i].Color == workspace[i + 1].Color)
|
||||||
|
{
|
||||||
|
remap[workspace[i].PalEntry] = workspace[i + 1].PalEntry;
|
||||||
|
workspace[i].Foreign = 2;
|
||||||
|
++i;
|
||||||
|
--k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find near matches
|
||||||
|
if (k > 0)
|
||||||
|
{
|
||||||
|
for (i = 0; i <= j; ++i)
|
||||||
|
{
|
||||||
|
if (workspace[i].Foreign == 1)
|
||||||
|
{
|
||||||
|
remap[workspace[i].PalEntry] = BestColor((uint32_t*)BaseColors,
|
||||||
|
RPART(workspace[i].Color), GPART(workspace[i].Color), BPART(workspace[i].Color),
|
||||||
|
1, 255);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// In ZDoom's new texture system, color 0 is used as the transparent color.
|
||||||
|
// But color 0 is also a valid color for Doom engine graphics. What to do?
|
||||||
|
// Simple. The default palette for every game has at least one duplicate
|
||||||
|
// color, so find a duplicate pair of palette entries, make one of them a
|
||||||
|
// duplicate of color 0, and remap every graphic so that it uses that entry
|
||||||
|
// instead of entry 0.
|
||||||
|
void MakeGoodRemap(uint32_t* BaseColors, uint8_t* Remap)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 256; i++) Remap[i] = i;
|
||||||
|
PalEntry color0 = BaseColors[0];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// First try for an exact match of color 0. Only Hexen does not have one.
|
||||||
|
for (i = 1; i < 256; ++i)
|
||||||
|
{
|
||||||
|
if (BaseColors[i] == color0)
|
||||||
|
{
|
||||||
|
Remap[0] = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is no duplicate of color 0, find the first set of duplicate
|
||||||
|
// colors and make one of them a duplicate of color 0. In Hexen's PLAYPAL
|
||||||
|
// colors 209 and 229 are the only duplicates, but we cannot assume
|
||||||
|
// anything because the player might be using a custom PLAYPAL where those
|
||||||
|
// entries are not duplicates.
|
||||||
|
if (Remap[0] == 0)
|
||||||
|
{
|
||||||
|
PalEntry sortcopy[256];
|
||||||
|
|
||||||
|
for (i = 0; i < 256; ++i)
|
||||||
|
{
|
||||||
|
sortcopy[i] = BaseColors[i] | (i << 24);
|
||||||
|
}
|
||||||
|
qsort(sortcopy, 256, 4, sortforremap);
|
||||||
|
for (i = 255; i > 0; --i)
|
||||||
|
{
|
||||||
|
if ((sortcopy[i] & 0xFFFFFF) == (sortcopy[i - 1] & 0xFFFFFF))
|
||||||
|
{
|
||||||
|
int new0 = sortcopy[i].a;
|
||||||
|
int dup = sortcopy[i - 1].a;
|
||||||
|
if (new0 > dup)
|
||||||
|
{
|
||||||
|
// Make the lower-numbered entry a copy of color 0. (Just because.)
|
||||||
|
std::swap(new0, dup);
|
||||||
|
}
|
||||||
|
Remap[0] = new0;
|
||||||
|
Remap[new0] = dup;
|
||||||
|
BaseColors[new0] = color0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there were no duplicates, InitPalette() will remap color 0 to the
|
||||||
|
// closest matching color. Hopefully nobody will use a palette where all
|
||||||
|
// 256 entries are different. :-)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,12 @@
|
||||||
int BestColor(const uint32_t* pal, int r, int g, int b, int first = 1, int num = 255);
|
int BestColor(const uint32_t* pal, int r, int g, int b, int first = 1, int num = 255);
|
||||||
int PTM_BestColor(const uint32_t* pal_in, int r, int g, int b, bool reverselookup, float powtable, int first = 1, int num = 255);
|
int PTM_BestColor(const uint32_t* pal_in, int r, int g, int b, bool reverselookup, float powtable, int first = 1, int num = 255);
|
||||||
void DoBlending(const PalEntry* from, PalEntry* to, int count, int r, int g, int b, int a);
|
void DoBlending(const PalEntry* from, PalEntry* to, int count, int r, int g, int b, int a);
|
||||||
|
|
||||||
|
// Given an array of colors, fills in remap with values to remap the
|
||||||
|
// passed array of colors to BaseColors. Used for loading palette downconversions of PNGs.
|
||||||
|
void MakeRemap(uint32_t* BaseColors, const uint32_t* colors, uint8_t* remap, const uint8_t* useful, int numcolors);
|
||||||
|
void MakeGoodRemap(uint32_t* BaseColors, uint8_t* Remap);
|
||||||
|
|
||||||
// Colorspace conversion RGB <-> HSV
|
// Colorspace conversion RGB <-> HSV
|
||||||
void RGBtoHSV (float r, float g, float b, float *h, float *s, float *v);
|
void RGBtoHSV (float r, float g, float b, float *h, float *s, float *v);
|
||||||
void HSVtoRGB (float *r, float *g, float *b, float h, float s, float v);
|
void HSVtoRGB (float *r, float *g, float *b, float h, float s, float v);
|
||||||
|
|
|
@ -63,9 +63,6 @@ FColorMatcher ColorMatcher;
|
||||||
/* Current color blending values */
|
/* Current color blending values */
|
||||||
int BlendR, BlendG, BlendB, BlendA;
|
int BlendR, BlendG, BlendB, BlendA;
|
||||||
|
|
||||||
static int sortforremap (const void *a, const void *b);
|
|
||||||
static int sortforremap2 (const void *a, const void *b);
|
|
||||||
|
|
||||||
/**************************/
|
/**************************/
|
||||||
/* Gamma correction stuff */
|
/* Gamma correction stuff */
|
||||||
/**************************/
|
/**************************/
|
||||||
|
@ -128,156 +125,6 @@ void FPalette::SetPalette (const uint8_t *colors)
|
||||||
BlackIndex = BestColor ((uint32_t *)BaseColors, 0, 0, 0, 0, 255);
|
BlackIndex = BestColor ((uint32_t *)BaseColors, 0, 0, 0, 0, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
// In ZDoom's new texture system, color 0 is used as the transparent color.
|
|
||||||
// But color 0 is also a valid color for Doom engine graphics. What to do?
|
|
||||||
// Simple. The default palette for every game has at least one duplicate
|
|
||||||
// color, so find a duplicate pair of palette entries, make one of them a
|
|
||||||
// duplicate of color 0, and remap every graphic so that it uses that entry
|
|
||||||
// instead of entry 0.
|
|
||||||
void FPalette::MakeGoodRemap ()
|
|
||||||
{
|
|
||||||
PalEntry color0 = BaseColors[0];
|
|
||||||
int i;
|
|
||||||
|
|
||||||
// First try for an exact match of color 0. Only Hexen does not have one.
|
|
||||||
for (i = 1; i < 256; ++i)
|
|
||||||
{
|
|
||||||
if (BaseColors[i] == color0)
|
|
||||||
{
|
|
||||||
Remap[0] = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there is no duplicate of color 0, find the first set of duplicate
|
|
||||||
// colors and make one of them a duplicate of color 0. In Hexen's PLAYPAL
|
|
||||||
// colors 209 and 229 are the only duplicates, but we cannot assume
|
|
||||||
// anything because the player might be using a custom PLAYPAL where those
|
|
||||||
// entries are not duplicates.
|
|
||||||
if (Remap[0] == 0)
|
|
||||||
{
|
|
||||||
PalEntry sortcopy[256];
|
|
||||||
|
|
||||||
for (i = 0; i < 256; ++i)
|
|
||||||
{
|
|
||||||
sortcopy[i] = BaseColors[i] | (i << 24);
|
|
||||||
}
|
|
||||||
qsort (sortcopy, 256, 4, sortforremap);
|
|
||||||
for (i = 255; i > 0; --i)
|
|
||||||
{
|
|
||||||
if ((sortcopy[i] & 0xFFFFFF) == (sortcopy[i-1] & 0xFFFFFF))
|
|
||||||
{
|
|
||||||
int new0 = sortcopy[i].a;
|
|
||||||
int dup = sortcopy[i-1].a;
|
|
||||||
if (new0 > dup)
|
|
||||||
{
|
|
||||||
// Make the lower-numbered entry a copy of color 0. (Just because.)
|
|
||||||
std::swap (new0, dup);
|
|
||||||
}
|
|
||||||
Remap[0] = new0;
|
|
||||||
Remap[new0] = dup;
|
|
||||||
BaseColors[new0] = color0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there were no duplicates, InitPalette() will remap color 0 to the
|
|
||||||
// closest matching color. Hopefully nobody will use a palette where all
|
|
||||||
// 256 entries are different. :-)
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sortforremap (const void *a, const void *b)
|
|
||||||
{
|
|
||||||
return (*(const uint32_t *)a & 0xFFFFFF) - (*(const uint32_t *)b & 0xFFFFFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct RemappingWork
|
|
||||||
{
|
|
||||||
uint32_t Color;
|
|
||||||
uint8_t Foreign; // 0 = local palette, 1 = foreign palette
|
|
||||||
uint8_t PalEntry; // Entry # in the palette
|
|
||||||
uint8_t Pad[2];
|
|
||||||
};
|
|
||||||
|
|
||||||
void FPalette::MakeRemap (const uint32_t *colors, uint8_t *remap, const uint8_t *useful, int numcolors) const
|
|
||||||
{
|
|
||||||
RemappingWork workspace[255+256];
|
|
||||||
int i, j, k;
|
|
||||||
|
|
||||||
// Fill in workspace with the colors from the passed palette and this palette.
|
|
||||||
// By sorting this array, we can quickly find exact matches so that we can
|
|
||||||
// minimize the time spent calling BestColor for near matches.
|
|
||||||
|
|
||||||
for (i = 1; i < 256; ++i)
|
|
||||||
{
|
|
||||||
workspace[i-1].Color = uint32_t(BaseColors[i]) & 0xFFFFFF;
|
|
||||||
workspace[i-1].Foreign = 0;
|
|
||||||
workspace[i-1].PalEntry = i;
|
|
||||||
}
|
|
||||||
for (i = k = 0, j = 255; i < numcolors; ++i)
|
|
||||||
{
|
|
||||||
if (useful == NULL || useful[i] != 0)
|
|
||||||
{
|
|
||||||
workspace[j].Color = colors[i] & 0xFFFFFF;
|
|
||||||
workspace[j].Foreign = 1;
|
|
||||||
workspace[j].PalEntry = i;
|
|
||||||
++j;
|
|
||||||
++k;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
remap[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
qsort (workspace, j, sizeof(RemappingWork), sortforremap2);
|
|
||||||
|
|
||||||
// Find exact matches
|
|
||||||
--j;
|
|
||||||
for (i = 0; i < j; ++i)
|
|
||||||
{
|
|
||||||
if (workspace[i].Foreign)
|
|
||||||
{
|
|
||||||
if (!workspace[i+1].Foreign && workspace[i].Color == workspace[i+1].Color)
|
|
||||||
{
|
|
||||||
remap[workspace[i].PalEntry] = workspace[i+1].PalEntry;
|
|
||||||
workspace[i].Foreign = 2;
|
|
||||||
++i;
|
|
||||||
--k;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find near matches
|
|
||||||
if (k > 0)
|
|
||||||
{
|
|
||||||
for (i = 0; i <= j; ++i)
|
|
||||||
{
|
|
||||||
if (workspace[i].Foreign == 1)
|
|
||||||
{
|
|
||||||
remap[workspace[i].PalEntry] = BestColor ((uint32_t *)BaseColors,
|
|
||||||
RPART(workspace[i].Color), GPART(workspace[i].Color), BPART(workspace[i].Color),
|
|
||||||
1, 255);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sortforremap2 (const void *a, const void *b)
|
|
||||||
{
|
|
||||||
const RemappingWork *ap = (const RemappingWork *)a;
|
|
||||||
const RemappingWork *bp = (const RemappingWork *)b;
|
|
||||||
|
|
||||||
if (ap->Color == bp->Color)
|
|
||||||
{
|
|
||||||
return bp->Foreign - ap->Foreign;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return ap->Color - bp->Color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int ReadPalette(int lumpnum, uint8_t *buffer)
|
int ReadPalette(int lumpnum, uint8_t *buffer)
|
||||||
{
|
{
|
||||||
if (lumpnum < 0)
|
if (lumpnum < 0)
|
||||||
|
@ -406,7 +253,7 @@ void InitPalette ()
|
||||||
ReadPalette(fileSystem.GetNumForName("PLAYPAL"), pal);
|
ReadPalette(fileSystem.GetNumForName("PLAYPAL"), pal);
|
||||||
|
|
||||||
GPalette.SetPalette (pal);
|
GPalette.SetPalette (pal);
|
||||||
GPalette.MakeGoodRemap ();
|
MakeGoodRemap ((uint32_t*)GPalette.BaseColors, GPalette.Remap);
|
||||||
ColorMatcher.SetPalette ((uint32_t *)GPalette.BaseColors);
|
ColorMatcher.SetPalette ((uint32_t *)GPalette.BaseColors);
|
||||||
|
|
||||||
if (GPalette.Remap[0] == 0)
|
if (GPalette.Remap[0] == 0)
|
||||||
|
|
|
@ -52,10 +52,6 @@ struct FPalette
|
||||||
|
|
||||||
uint8_t WhiteIndex; // white in original palette index
|
uint8_t WhiteIndex; // white in original palette index
|
||||||
uint8_t BlackIndex; // black in original palette index
|
uint8_t BlackIndex; // black in original palette index
|
||||||
|
|
||||||
// Given an array of colors, fills in remap with values to remap the
|
|
||||||
// passed array of colors to this palette.
|
|
||||||
void MakeRemap (const uint32_t *colors, uint8_t *remap, const uint8_t *useful, int numcolors) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern FPalette GPalette;
|
extern FPalette GPalette;
|
||||||
|
|
Loading…
Reference in a new issue