GRAPHICS: Use standard palettes in ManagedSurface

This commit is contained in:
Cameron Cawley 2023-02-22 10:13:58 +00:00 committed by Eugene Sandulenko
parent 95f6d7a227
commit ee35a3d268
2 changed files with 59 additions and 76 deletions

View file

@ -32,14 +32,14 @@ ManagedSurface::ManagedSurface() :
w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format), w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format),
_disposeAfterUse(DisposeAfterUse::NO), _owner(nullptr), _disposeAfterUse(DisposeAfterUse::NO), _owner(nullptr),
_transparentColor(0),_transparentColorSet(false), _paletteSet(false) { _transparentColor(0),_transparentColorSet(false), _paletteSet(false) {
Common::fill(&_palette[0], &_palette[256], 0); memset(_palette, 0, sizeof(_palette));
} }
ManagedSurface::ManagedSurface(const ManagedSurface &surf) : ManagedSurface::ManagedSurface(const ManagedSurface &surf) :
w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format), w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format),
_disposeAfterUse(DisposeAfterUse::NO), _owner(nullptr), _disposeAfterUse(DisposeAfterUse::NO), _owner(nullptr),
_transparentColor(0), _transparentColorSet(false), _paletteSet(false) { _transparentColor(0), _transparentColorSet(false), _paletteSet(false) {
Common::fill(&_palette[0], &_palette[256], 0); memset(_palette, 0, sizeof(_palette));
*this = surf; *this = surf;
} }
@ -47,7 +47,7 @@ ManagedSurface::ManagedSurface(int width, int height) :
w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format), w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format),
_disposeAfterUse(DisposeAfterUse::NO), _owner(nullptr), _disposeAfterUse(DisposeAfterUse::NO), _owner(nullptr),
_transparentColor(0), _transparentColorSet(false), _paletteSet(false) { _transparentColor(0), _transparentColorSet(false), _paletteSet(false) {
Common::fill(&_palette[0], &_palette[256], 0); memset(_palette, 0, sizeof(_palette));
create(width, height); create(width, height);
} }
@ -55,7 +55,7 @@ ManagedSurface::ManagedSurface(int width, int height, const Graphics::PixelForma
w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format), w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format),
_disposeAfterUse(DisposeAfterUse::NO), _owner(nullptr), _disposeAfterUse(DisposeAfterUse::NO), _owner(nullptr),
_transparentColor(0), _transparentColorSet(false), _paletteSet(false) { _transparentColor(0), _transparentColorSet(false), _paletteSet(false) {
Common::fill(&_palette[0], &_palette[256], 0); memset(_palette, 0, sizeof(_palette));
create(width, height, pixelFormat); create(width, height, pixelFormat);
} }
@ -63,7 +63,7 @@ ManagedSurface::ManagedSurface(ManagedSurface &surf, const Common::Rect &bounds)
w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format), w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format),
_disposeAfterUse(DisposeAfterUse::NO), _owner(nullptr), _disposeAfterUse(DisposeAfterUse::NO), _owner(nullptr),
_transparentColor(0), _transparentColorSet(false), _paletteSet(false) { _transparentColor(0), _transparentColorSet(false), _paletteSet(false) {
Common::fill(&_palette[0], &_palette[256], 0); memset(_palette, 0, sizeof(_palette));
create(surf, bounds); create(surf, bounds);
} }
@ -132,7 +132,7 @@ ManagedSurface &ManagedSurface::operator=(const ManagedSurface &surf) {
_transparentColorSet = surf._transparentColorSet; _transparentColorSet = surf._transparentColorSet;
_transparentColor = surf._transparentColor; _transparentColor = surf._transparentColor;
_paletteSet = surf._paletteSet; _paletteSet = surf._paletteSet;
Common::copy(&surf._palette[0], &surf._palette[256], _palette); memcpy(_palette, surf._palette, sizeof(_palette));
} }
return *this; return *this;
@ -176,7 +176,7 @@ void ManagedSurface::create(ManagedSurface &surf, const Common::Rect &bounds) {
_transparentColorSet = surf._transparentColorSet; _transparentColorSet = surf._transparentColorSet;
_transparentColor = surf._transparentColor; _transparentColor = surf._transparentColor;
_paletteSet = surf._paletteSet; _paletteSet = surf._paletteSet;
Common::copy(&surf._palette[0], &surf._palette[256], _palette); memcpy(_palette, surf._palette, sizeof(_palette));
} }
void ManagedSurface::free() { void ManagedSurface::free() {
@ -205,7 +205,7 @@ void ManagedSurface::copyFrom(const ManagedSurface &surf) {
_transparentColorSet = surf._transparentColorSet; _transparentColorSet = surf._transparentColorSet;
_transparentColor = surf._transparentColor; _transparentColor = surf._transparentColor;
_paletteSet = surf._paletteSet; _paletteSet = surf._paletteSet;
Common::copy(&surf._palette[0], &surf._palette[256], _palette); memcpy(_palette, surf._palette, sizeof(_palette));
} }
void ManagedSurface::copyFrom(const Surface &surf) { void ManagedSurface::copyFrom(const Surface &surf) {
@ -223,7 +223,7 @@ void ManagedSurface::copyFrom(const Surface &surf) {
_transparentColorSet = false; _transparentColorSet = false;
_transparentColor = 0; _transparentColor = 0;
_paletteSet = false; _paletteSet = false;
Common::fill(&_palette[0], &_palette[256], 0); memset(_palette, 0, sizeof(_palette));
} }
void ManagedSurface::blitFrom(const Surface &src) { void ManagedSurface::blitFrom(const Surface &src) {
@ -271,7 +271,7 @@ void ManagedSurface::blitFrom(const ManagedSurface &src, const Common::Rect &src
} }
void ManagedSurface::blitFromInner(const Surface &src, const Common::Rect &srcRect, void ManagedSurface::blitFromInner(const Surface &src, const Common::Rect &srcRect,
const Common::Rect &destRect, const uint32 *srcPalette) { const Common::Rect &destRect, const byte *srcPalette) {
if (destRect.isEmpty()) if (destRect.isEmpty())
return; return;
@ -300,12 +300,8 @@ void ManagedSurface::blitFromInner(const Surface &src, const Common::Rect &srcRe
uint32 alphaMask = 0; uint32 alphaMask = 0;
if (srcFormat.isCLUT8()) { if (srcFormat.aBits() > 0)
alphaMask = 0xff000000u; alphaMask = (((static_cast<uint32>(1) << (srcFormat.aBits() - 1)) - 1) * 2 + 1) << srcFormat.aShift;
} else {
if (srcFormat.aBits() > 0)
alphaMask = (((static_cast<uint32>(1) << (srcFormat.aBits() - 1)) - 1) * 2 + 1) << srcFormat.aShift;
}
const bool noScale = scaleX == SCALE_THRESHOLD && scaleY == SCALE_THRESHOLD; const bool noScale = scaleX == SCALE_THRESHOLD && scaleY == SCALE_THRESHOLD;
for (int destY = destRect.top, scaleYCtr = 0; destY < destRect.bottom; ++destY, scaleYCtr += scaleY) { for (int destY = destRect.top, scaleYCtr = 0; destY < destRect.bottom; ++destY, scaleYCtr += scaleY) {
@ -343,28 +339,23 @@ void ManagedSurface::blitFromInner(const Surface &src, const Common::Rect &srcRe
} }
uint32 col = 0; uint32 col = 0;
if (srcFormat.isCLUT8()) { // Use the src's pixel format to split up the source pixel
assert(srcPalette != nullptr); // Catch the cases when palette is missing if (srcFormat.bytesPerPixel == 1)
// Get the palette color col = *reinterpret_cast<const uint8 *>(srcVal);
col = srcPalette[*srcVal]; else if (srcFormat.bytesPerPixel == 2)
} else { col = *reinterpret_cast<const uint16 *>(srcVal);
// Use the src's pixel format to split up the source pixel else if (srcFormat.bytesPerPixel == 4)
if (srcFormat.bytesPerPixel == 1) col = *reinterpret_cast<const uint32 *>(srcVal);
col = *reinterpret_cast<const uint8 *>(srcVal); else
else if (srcFormat.bytesPerPixel == 2) col = READ_UINT24(srcVal);
col = *reinterpret_cast<const uint16 *>(srcVal);
else if (srcFormat.bytesPerPixel == 4)
col = *reinterpret_cast<const uint32 *>(srcVal);
else
col = READ_UINT24(srcVal);
}
const bool isOpaque = ((col & alphaMask) == alphaMask); const bool isOpaque = srcFormat.isCLUT8() ? true : ((col & alphaMask) == alphaMask);
const bool isTransparent = srcFormat.isCLUT8() ? false : ((col & alphaMask) == 0);
uint32 destPixel = 0; uint32 destPixel = 0;
// Need to check isOpaque in case alpha mask is 0 // Need to check isOpaque in case alpha mask is 0
if (!isOpaque && (col & alphaMask) == 0) { if (!isOpaque && isTransparent) {
// Completely transparent, so skip // Completely transparent, so skip
continue; continue;
} else if (isOpaque && isSameFormat) { } else if (isOpaque && isSameFormat) {
@ -376,10 +367,10 @@ void ManagedSurface::blitFromInner(const Surface &src, const Common::Rect &srcRe
// Different format or partially transparent // Different format or partially transparent
if (srcFormat.isCLUT8()) { if (srcFormat.isCLUT8()) {
rSrc = col & 0xff; rSrc = srcPalette[(col * 3) + 0];
gSrc = (col >> 8) & 0xff; gSrc = srcPalette[(col * 3) + 1];
bSrc = (col >> 16) & 0xff; bSrc = srcPalette[(col * 3) + 2];
aSrc = (col >> 24) & 0xff; aSrc = 0xff;
} else { } else {
srcFormat.colorToARGB(col, aSrc, rSrc, gSrc, bSrc); srcFormat.colorToARGB(col, aSrc, rSrc, gSrc, bSrc);
} }
@ -505,24 +496,22 @@ void ManagedSurface::transBlitFrom(const ManagedSurface &src, const Common::Rect
const Surface *mask, bool maskOnly) { const Surface *mask, bool maskOnly) {
if (transColor == (uint32)-1 && src._transparentColorSet) if (transColor == (uint32)-1 && src._transparentColorSet)
transColor = src._transparentColor; transColor = src._transparentColor;
const uint32 *srcPalette = src._paletteSet ? src._palette : nullptr; const byte *srcPalette = src._paletteSet ? src._palette : nullptr;
const uint32 *dstPalette = _paletteSet ? _palette : nullptr; const byte *dstPalette = _paletteSet ? _palette : nullptr;
transBlitFromInner(src._innerSurface, srcRect, destRect, transColor, flipped, overrideColor, transBlitFromInner(src._innerSurface, srcRect, destRect, transColor, flipped, overrideColor,
srcAlpha, srcPalette, dstPalette, mask, maskOnly); srcAlpha, srcPalette, dstPalette, mask, maskOnly);
} }
static uint findBestColor(const uint32 *palette, byte cr, byte cg, byte cb) { static uint findBestColor(const byte *palette, byte cr, byte cg, byte cb) {
uint bestColor = 0; uint bestColor = 0;
double min = 0xFFFFFFFF; double min = 0xFFFFFFFF;
for (uint i = 0; i < 256; ++i) { for (uint i = 0; i < 256; ++i) {
uint col = palette[i]; int rmean = (*(palette + 3 * i + 0) + cr) / 2;
int r = *(palette + 3 * i + 0) - cr;
int rmean = ((col & 0xff) + cr) / 2; int g = *(palette + 3 * i + 1) - cg;
int r = (col & 0xff) - cr; int b = *(palette + 3 * i + 2) - cb;
int g = ((col >> 8) & 0xff) - cg;
int b = ((col >> 16) & 0xff) - cb;
double dist = sqrt((((512 + rmean) * r * r) >> 8) + 4 * g * g + (((767 - rmean) * b * b) >> 8)); double dist = sqrt((((512 + rmean) * r * r) >> 8) + 4 * g * g + (((767 - rmean) * b * b) >> 8));
if (min > dist) { if (min > dist) {
@ -534,15 +523,21 @@ static uint findBestColor(const uint32 *palette, byte cr, byte cg, byte cb) {
return bestColor; return bestColor;
} }
static byte *createPaletteLookup(const uint32 *srcPalette, const uint32 *dstPalette) { static byte *createPaletteLookup(const byte *srcPalette, const byte *dstPalette) {
byte *lookup = new byte[256]; byte *lookup = new byte[256];
for (int i = 0; i < 256; i++) { for (int i = 0; i < 256; i++) {
uint col = srcPalette[i]; byte rSrc = srcPalette[(i * 3) + 0];
if (col == dstPalette[i]) { byte gSrc = srcPalette[(i * 3) + 1];
byte bSrc = srcPalette[(i * 3) + 2];
byte rDst = dstPalette[(i * 3) + 0];
byte gDst = dstPalette[(i * 3) + 1];
byte bDst = dstPalette[(i * 3) + 2];
if (rSrc == rDst && gSrc == gDst && bSrc == bDst) {
lookup[i] = i; lookup[i] = i;
} else { } else {
lookup[i] = findBestColor(dstPalette, col & 0xff, (col >> 8) & 0xff, (col >> 16) & 0xff); lookup[i] = findBestColor(dstPalette, rSrc, gSrc, bSrc);
} }
} }
@ -551,18 +546,17 @@ static byte *createPaletteLookup(const uint32 *srcPalette, const uint32 *dstPale
template<typename TSRC, typename TDEST> template<typename TSRC, typename TDEST>
void transBlitPixel(TSRC srcVal, TDEST &destVal, const Graphics::PixelFormat &srcFormat, const Graphics::PixelFormat &destFormat, void transBlitPixel(TSRC srcVal, TDEST &destVal, const Graphics::PixelFormat &srcFormat, const Graphics::PixelFormat &destFormat,
uint32 overrideColor, uint32 srcAlpha, const uint32 *srcPalette, const byte *lookup) { uint32 overrideColor, uint32 srcAlpha, const byte *srcPalette, const byte *lookup) {
// Decode and re-encode each pixel // Decode and re-encode each pixel
byte aSrc, rSrc, gSrc, bSrc; byte aSrc, rSrc, gSrc, bSrc;
if (srcFormat.isCLUT8()) { if (srcFormat.isCLUT8()) {
assert(srcPalette != nullptr); // Catch the cases when palette is missing assert(srcPalette != nullptr); // Catch the cases when palette is missing
// Get the palette color // Get the palette color
const uint32 col = srcPalette[srcVal]; rSrc = srcPalette[(srcVal * 3) + 0];
rSrc = col & 0xff; gSrc = srcPalette[(srcVal * 3) + 1];
gSrc = (col >> 8) & 0xff; bSrc = srcPalette[(srcVal * 3) + 2];
bSrc = (col >> 16) & 0xff; aSrc = 0xff;
aSrc = (col >> 24) & 0xff;
} else { } else {
srcFormat.colorToARGB(srcVal, aSrc, rSrc, gSrc, bSrc); srcFormat.colorToARGB(srcVal, aSrc, rSrc, gSrc, bSrc);
} }
@ -598,7 +592,7 @@ void transBlitPixel(TSRC srcVal, TDEST &destVal, const Graphics::PixelFormat &sr
template<> template<>
void transBlitPixel<byte, byte>(byte srcVal, byte &destVal, const Graphics::PixelFormat &srcFormat, const Graphics::PixelFormat &destFormat, void transBlitPixel<byte, byte>(byte srcVal, byte &destVal, const Graphics::PixelFormat &srcFormat, const Graphics::PixelFormat &destFormat,
uint32 overrideColor, uint32 srcAlpha, const uint32 *srcPalette, const byte *lookup) { uint32 overrideColor, uint32 srcAlpha, const byte *srcPalette, const byte *lookup) {
if (srcAlpha == 0) { if (srcAlpha == 0) {
// Completely transparent, so skip // Completely transparent, so skip
return; return;
@ -612,8 +606,8 @@ void transBlitPixel<byte, byte>(byte srcVal, byte &destVal, const Graphics::Pixe
template<typename TSRC, typename TDEST> template<typename TSRC, typename TDEST>
void transBlit(const Surface &src, const Common::Rect &srcRect, ManagedSurface &dest, const Common::Rect &destRect, void transBlit(const Surface &src, const Common::Rect &srcRect, ManagedSurface &dest, const Common::Rect &destRect,
TSRC transColor, bool flipped, uint32 overrideColor, uint32 srcAlpha, const uint32 *srcPalette, TSRC transColor, bool flipped, uint32 overrideColor, uint32 srcAlpha, const byte *srcPalette,
const uint32 *dstPalette, const Surface *mask, bool maskOnly) { const byte *dstPalette, const Surface *mask, bool maskOnly) {
int scaleX = SCALE_THRESHOLD * srcRect.width() / destRect.width(); int scaleX = SCALE_THRESHOLD * srcRect.width() / destRect.width();
int scaleY = SCALE_THRESHOLD * srcRect.height() / destRect.height(); int scaleY = SCALE_THRESHOLD * srcRect.height() / destRect.height();
byte rst = 0, gst = 0, bst = 0, rdt = 0, gdt = 0, bdt = 0; byte rst = 0, gst = 0, bst = 0, rdt = 0, gdt = 0, bdt = 0;
@ -704,7 +698,7 @@ void transBlit(const Surface &src, const Common::Rect &srcRect, ManagedSurface &
void ManagedSurface::transBlitFromInner(const Surface &src, const Common::Rect &srcRect, void ManagedSurface::transBlitFromInner(const Surface &src, const Common::Rect &srcRect,
const Common::Rect &destRect, uint32 transColor, bool flipped, uint32 overrideColor, const Common::Rect &destRect, uint32 transColor, bool flipped, uint32 overrideColor,
uint32 srcAlpha, const uint32 *srcPalette, const uint32 *dstPalette, const Surface *mask, bool maskOnly) { uint32 srcAlpha, const byte *srcPalette, const byte *dstPalette, const Surface *mask, bool maskOnly) {
if (src.w == 0 || src.h == 0 || destRect.width() == 0 || destRect.height() == 0) if (src.w == 0 || src.h == 0 || destRect.width() == 0 || destRect.height() == 0)
return; return;
@ -750,23 +744,12 @@ void ManagedSurface::clear(uint32 color) {
void ManagedSurface::grabPalette(byte *colors, uint start, uint num) const { void ManagedSurface::grabPalette(byte *colors, uint start, uint num) const {
assert(start < 256 && (start + num) <= 256); assert(start < 256 && (start + num) <= 256);
const uint32 *src = &_palette[start]; memcpy(colors, _palette + 3 * start, 3 * num);
for (; num > 0; --num, colors += 3) {
uint32 p = *src++;
colors[0] = p & 0xff;
colors[1] = (p >> 8) & 0xff;
colors[2] = (p >> 16) & 0xff;
}
} }
void ManagedSurface::setPalette(const byte *colors, uint start, uint num) { void ManagedSurface::setPalette(const byte *colors, uint start, uint num) {
assert(start < 256 && (start + num) <= 256); assert(start < 256 && (start + num) <= 256);
uint32 *dest = &_palette[start]; memcpy(_palette + 3 * start, colors, 3 * num);
for (; num > 0; --num, colors += 3) {
*dest++ = colors[0] | (colors[1] << 8) | (colors[2] << 16) | (0xff << 24);
}
_paletteSet = true; _paletteSet = true;

View file

@ -77,21 +77,21 @@ private:
/** /**
* Local palette for 8-bit images. * Local palette for 8-bit images.
*/ */
uint32 _palette[256]; byte _palette[256 * 3];
bool _paletteSet; bool _paletteSet;
protected: protected:
/** /**
* Inner method for blitting. * Inner method for blitting.
*/ */
void blitFromInner(const Surface &src, const Common::Rect &srcRect, void blitFromInner(const Surface &src, const Common::Rect &srcRect,
const Common::Rect &destRect, const uint32 *srcPalette); const Common::Rect &destRect, const byte *srcPalette);
/** /**
* Inner method for copying another surface into this one at a given destination position. * Inner method for copying another surface into this one at a given destination position.
*/ */
void transBlitFromInner(const Surface &src, const Common::Rect &srcRect, void transBlitFromInner(const Surface &src, const Common::Rect &srcRect,
const Common::Rect &destRect, uint32 transColor, bool flipped, uint32 overrideColor, const Common::Rect &destRect, uint32 transColor, bool flipped, uint32 overrideColor,
uint32 srcAlpha, const uint32 *srcPalette, const uint32 *dstPalette, const Surface *mask, bool maskOnly); uint32 srcAlpha, const byte *srcPalette, const byte *dstPalette, const Surface *mask, bool maskOnly);
public: public:
/** /**
* Clip the given source bounds so the passed destBounds will be entirely on-screen. * Clip the given source bounds so the passed destBounds will be entirely on-screen.