aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorJohannes Schickel2009-09-20 22:59:30 +0000
committerJohannes Schickel2009-09-20 22:59:30 +0000
commit6b9299e863c08a09875de75dfd3bcc49e56fc9d1 (patch)
tree7044d4212ee43be83db79119cb522a8b3725ba1a /engines
parenta9f1063ae1942475516b7e200142728bfd8026e9 (diff)
downloadscummvm-rg350-6b9299e863c08a09875de75dfd3bcc49e56fc9d1.tar.gz
scummvm-rg350-6b9299e863c08a09875de75dfd3bcc49e56fc9d1.tar.bz2
scummvm-rg350-6b9299e863c08a09875de75dfd3bcc49e56fc9d1.zip
Implement more precise palette conversion in Palette::save. This makes the output look more like the original (compared against E-UAE), but still not perfect.
svn-id: r44221
Diffstat (limited to 'engines')
-rw-r--r--engines/cine/pal.cpp45
1 files changed, 26 insertions, 19 deletions
diff --git a/engines/cine/pal.cpp b/engines/cine/pal.cpp
index ea8f6fbaab..582a707be7 100644
--- a/engines/cine/pal.cpp
+++ b/engines/cine/pal.cpp
@@ -103,14 +103,7 @@ void loadRelatedPalette(const char *fileName) {
}
}
-/*! \brief Shift byte to the left by given amount (Handles negative shifting amounts too, otherwise this would be trivial). */
-byte shiftByteLeft(const byte value, const signed shiftLeft) {
- if (shiftLeft >= 0)
- return value << shiftLeft;
- else // right shift with negative shiftLeft values
- return value >> abs(shiftLeft);
-}
-
+namespace {
/*! \brief Is given endian type big endian? (Handles native endian type too, otherwise this would be trivial). */
bool isBigEndian(const EndianType endian) {
assert(endian == CINE_NATIVE_ENDIAN || endian == CINE_LITTLE_ENDIAN || endian == CINE_BIG_ENDIAN);
@@ -138,6 +131,15 @@ int bytePos(const int bitPos, const int numBytes, const bool bigEndian) {
return bitPos / 8;
}
+/*! \brief Calculate the value of "base" to the power of "power". */
+int power(int base, int power) {
+ int result = 1;
+ while (power--)
+ result *= base;
+ return result;
+}
+} // end of anonymous namespace
+
// a.k.a. palRotate
Palette &Palette::rotateRight(byte firstIndex, byte lastIndex, signed rotationAmount) {
assert(rotationAmount == 0 || rotationAmount == 1);
@@ -317,25 +319,30 @@ byte *Palette::save(byte *buf, const uint size, const Graphics::PixelFormat form
// Clear the part of the output palette we're going to be writing to with all black
memset(buf, 0, format.bytesPerPixel * numColors);
- // Calculate how much bit shifting the color components need (for positioning them correctly)
- const signed rShiftLeft = (colorFormat().rLoss - (signed) format.rLoss) + (format.rShift % 8);
- const signed gShiftLeft = (colorFormat().gLoss - (signed) format.gLoss) + (format.gShift % 8);
- const signed bShiftLeft = (colorFormat().bLoss - (signed) format.bLoss) + (format.bShift % 8);
+ // Calculate original R/G/B max values
+ const int rOrigMax = power(2, 8 - colorFormat().rLoss) - 1;
+ const int gOrigMax = power(2, 8 - colorFormat().gLoss) - 1;
+ const int bOrigMax = power(2, 8 - colorFormat().bLoss) - 1;
- // Calculate the byte masks for each color component (for masking away excess bits)
- const byte rMask = format.rMax() << (format.rShift % 8);
- const byte gMask = format.gMax() << (format.gShift % 8);
- const byte bMask = format.bMax() << (format.bShift % 8);
+ // Calculate new R/G/B max values
+ const int rNewMax = power(2, 8 - format.rLoss) - 1;
+ const int gNewMax = power(2, 8 - format.gLoss) - 1;
+ const int bNewMax = power(2, 8 - format.bLoss) - 1;
+ // Calculate the byte position
const int rBytePos = bytePos(format.rShift, format.bytesPerPixel, isBigEndian(endian));
const int gBytePos = bytePos(format.gShift, format.bytesPerPixel, isBigEndian(endian));
const int bBytePos = bytePos(format.bShift, format.bytesPerPixel, isBigEndian(endian));
// Save the palette to the output in the specified format
for (uint i = firstIndex; i < firstIndex + numColors; i++) {
- buf[i * format.bytesPerPixel + rBytePos] |= (shiftByteLeft(_colors[i].r, rShiftLeft) & rMask);
- buf[i * format.bytesPerPixel + gBytePos] |= (shiftByteLeft(_colors[i].g, gShiftLeft) & gMask);
- buf[i * format.bytesPerPixel + bBytePos] |= (shiftByteLeft(_colors[i].b, bShiftLeft) & bMask);
+ const uint r = (_colors[i].r * rNewMax) / rOrigMax;
+ const uint g = (_colors[i].g * gNewMax) / gOrigMax;
+ const uint b = (_colors[i].b * bNewMax) / bOrigMax;
+
+ buf[i * format.bytesPerPixel + rBytePos] |= r << (format.rShift % 8);
+ buf[i * format.bytesPerPixel + gBytePos] |= g << (format.gShift % 8);
+ buf[i * format.bytesPerPixel + bBytePos] |= b << (format.bShift % 8);
}
// Return the pointer to the output palette