Change RgbMap behavior to act like a cache of Palette::findBestfit() calls

Instead of calling findBestfit() for all RGBA colors in
RgbMap::regenerate(), we mark all entries as invalid, and then we
validate them only when the user require one specific entry from
RgbMap::mapColor(). With this we avoid a lot of unnecessary computations
each time the palette changes.
This commit is contained in:
David Capello 2015-07-03 14:34:54 -03:00
parent 48a1af7342
commit 66168d6b06
2 changed files with 25 additions and 18 deletions

View File

@ -26,6 +26,7 @@ RgbMap::RgbMap()
, m_map(MAPSIZE)
, m_palette(NULL)
, m_modifications(0)
, m_maskIndex(0)
{
}
@ -39,24 +40,21 @@ void RgbMap::regenerate(const Palette* palette, int mask_index)
{
m_palette = palette;
m_modifications = palette->getModifications();
m_maskIndex = mask_index;
// TODO This is slow for 256 colors 32*32*32*8 findBestfit calls
// Mark all entries as invalid (need to be regenerated)
for (uint16_t& entry : m_map)
entry |= INVALID;
}
int i = 0;
for (int r=0; r<RSIZE; ++r) {
for (int g=0; g<GSIZE; ++g) {
for (int b=0; b<BSIZE; ++b) {
for (int a=0; a<ASIZE; ++a) {
m_map[i++] =
palette->findBestfit(
scale_5bits_to_8bits(r),
scale_5bits_to_8bits(g),
scale_5bits_to_8bits(b),
scale_3bits_to_8bits(a), mask_index);
}
}
}
}
int RgbMap::generateEntry(int i, int r, int g, int b, int a) const
{
return m_map[i] =
m_palette->findBestfit(
scale_5bits_to_8bits(r>>3),
scale_5bits_to_8bits(g>>3),
scale_5bits_to_8bits(b>>3),
scale_3bits_to_8bits(a>>5), m_maskIndex);
}
} // namespace doc

View File

@ -17,7 +17,11 @@ namespace doc {
class Palette;
// It acts like a cache for Palette:findBestfit() calls.
class RgbMap : public Object {
// Bit activated on m_map entries that aren't yet calculated.
const int INVALID = 256;
public:
RgbMap();
@ -30,13 +34,18 @@ namespace doc {
ASSERT(b >= 0 && b < 256);
ASSERT(a >= 0 && a < 256);
// bits -> bbbbbgggggrrrrraaa
return m_map[(a>>5) | ((b>>3) << 3) | ((g>>3) << 8) | ((r>>3) << 13)];
int i = (a>>5) | ((b>>3) << 3) | ((g>>3) << 8) | ((r>>3) << 13);
int v = m_map[i];
return (v & INVALID) ? generateEntry(i, r, g, b, a): v;
}
private:
std::vector<uint8_t> m_map;
int generateEntry(int i, int r, int g, int b, int a) const;
mutable std::vector<uint16_t> m_map;
const Palette* m_palette;
int m_modifications;
int m_maskIndex;
DISABLE_COPYING(RgbMap);
};