aboutsummaryrefslogtreecommitdiff
path: root/graphics
diff options
context:
space:
mode:
Diffstat (limited to 'graphics')
-rw-r--r--graphics/conversion.cpp152
-rw-r--r--graphics/conversion.h76
-rw-r--r--graphics/cursorman.cpp29
-rw-r--r--graphics/cursorman.h36
-rw-r--r--graphics/dither.cpp1
-rw-r--r--graphics/dither.h13
-rw-r--r--graphics/jpeg.cpp638
-rw-r--r--graphics/jpeg.h118
-rw-r--r--graphics/module.mk2
-rw-r--r--graphics/pixelformat.h39
-rw-r--r--graphics/scaler.cpp9
-rw-r--r--graphics/scaler/thumbnail_intern.cpp20
-rw-r--r--graphics/video/coktelvideo/coktelvideo.cpp5
13 files changed, 1095 insertions, 43 deletions
diff --git a/graphics/conversion.cpp b/graphics/conversion.cpp
new file mode 100644
index 0000000000..1863814c1d
--- /dev/null
+++ b/graphics/conversion.cpp
@@ -0,0 +1,152 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#include "graphics/conversion.h"
+
+namespace Graphics {
+
+// TODO: YUV to RGB conversion function
+
+// Function to blit a rect from one color format to another
+bool crossBlit(byte *dst, const byte *src, int dstpitch, int srcpitch,
+ int w, int h, const Graphics::PixelFormat &dstFmt, const Graphics::PixelFormat &srcFmt) {
+ // Error out if conversion is impossible
+ if ((srcFmt.bytesPerPixel == 1) || (dstFmt.bytesPerPixel == 1)
+ || (!srcFmt.bytesPerPixel) || (!dstFmt.bytesPerPixel)
+ || (srcFmt.bytesPerPixel > dstFmt.bytesPerPixel))
+ return false;
+
+ // Don't perform unnecessary conversion
+ if (srcFmt == dstFmt) {
+ if (dst == src)
+ return true;
+ if (dstpitch == srcpitch && ((w * dstFmt.bytesPerPixel) == dstpitch)) {
+ memcpy(dst,src,dstpitch * h);
+ return true;
+ } else {
+ for (int i = 0; i < h; i++) {
+ memcpy(dst,src,w * dstFmt.bytesPerPixel);
+ dst += dstpitch;
+ src += srcpitch;
+ }
+ return true;
+ }
+ }
+
+ // Faster, but larger, to provide optimized handling for each case.
+ int srcDelta, dstDelta;
+ srcDelta = (srcpitch - w * srcFmt.bytesPerPixel);
+ dstDelta = (dstpitch - w * dstFmt.bytesPerPixel);
+
+ // TODO: optimized cases for dstDelta of 0
+ uint8 r, g, b, a;
+ if (dstFmt.bytesPerPixel == 2) {
+ uint16 color;
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < w; x++, src += 2, dst += 2) {
+ color = *(uint16 *) src;
+ srcFmt.colorToARGB(color, a, r, g, b);
+ color = dstFmt.ARGBToColor(a, r, g, b);
+ *(uint16 *) dst = color;
+ }
+ src += srcDelta;
+ dst += dstDelta;
+ }
+ } else if (dstFmt.bytesPerPixel == 3) {
+ uint32 color;
+ uint8 *col = (uint8 *) &color;
+#ifdef SCUMM_BIG_ENDIAN
+ col++;
+#endif
+ if (srcFmt.bytesPerPixel == 2) {
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < w; x++, src += 2, dst += 3) {
+ color = *(uint16 *) src;
+ srcFmt.colorToARGB(color, a, r, g, b);
+ color = dstFmt.ARGBToColor(a, r, g, b);
+ memcpy(dst, col, 3);
+ }
+ src += srcDelta;
+ dst += dstDelta;
+ }
+ } else {
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < w; x++, src += 3, dst += 3) {
+ uint8 r, g, b, a;
+ memcpy(col, src, 3);
+ srcFmt.colorToARGB(color, a, r, g, b);
+ color = dstFmt.ARGBToColor(a, r, g, b);
+ memcpy(dst, col, 3);
+ }
+ src += srcDelta;
+ dst += dstDelta;
+ }
+ }
+ } else if (dstFmt.bytesPerPixel == 4) {
+ uint32 color;
+ if (srcFmt.bytesPerPixel == 2) {
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < w; x++, src += 2, dst += 4) {
+ color = *(uint16 *) src;
+ srcFmt.colorToARGB(color, a, r, g, b);
+ color = dstFmt.ARGBToColor(a, r, g, b);
+ *(uint32 *) dst = color;
+ }
+ src += srcDelta;
+ dst += dstDelta;
+ }
+ } else if (srcFmt.bytesPerPixel == 3) {
+ uint8 *col = (uint8 *)&color;
+#ifdef SCUMM_BIG_ENDIAN
+ col++;
+#endif
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < w; x++, src += 2, dst += 4) {
+ memcpy(col, src, 3);
+ srcFmt.colorToARGB(color, a, r, g, b);
+ color = dstFmt.ARGBToColor(a, r, g, b);
+ *(uint32 *) dst = color;
+ }
+ src += srcDelta;
+ dst += dstDelta;
+ }
+ } else {
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < w; x++, src += 4, dst += 4) {
+ color = *(uint32 *) src;
+ srcFmt.colorToARGB(color, a, r, g, b);
+ color = dstFmt.ARGBToColor(a, r, g, b);
+ *(uint32 *) dst = color;
+ }
+ src += srcDelta;
+ dst += dstDelta;
+ }
+ }
+ } else {
+ return false;
+ }
+ return true;
+}
+
+} // end of namespace Graphics
diff --git a/graphics/conversion.h b/graphics/conversion.h
new file mode 100644
index 0000000000..b0314046b9
--- /dev/null
+++ b/graphics/conversion.h
@@ -0,0 +1,76 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GRAPHICS_CONVERSION_H
+#define GRAPHICS_CONVERSION_H
+
+#include "common/util.h"
+#include "graphics/pixelformat.h"
+
+namespace Graphics {
+
+/** Converting a color from YUV to RGB colorspace. */
+inline static void YUV2RGB(byte y, byte u, byte v, byte &r, byte &g, byte &b) {
+ r = CLIP<int>(y + ((1357 * (v - 128)) >> 10), 0, 255);
+ g = CLIP<int>(y - (( 691 * (v - 128)) >> 10) - ((333 * (u - 128)) >> 10), 0, 255);
+ b = CLIP<int>(y + ((1715 * (u - 128)) >> 10), 0, 255);
+}
+
+/** Converting a color from RGB to YUV colorspace. */
+inline static void RGB2YUV(byte r, byte g, byte b, byte &y, byte &u, byte &v) {
+ y = CLIP<int>( ((r * 306) >> 10) + ((g * 601) >> 10) + ((b * 117) >> 10) , 0, 255);
+ u = CLIP<int>(-((r * 172) >> 10) - ((g * 340) >> 10) + ((b * 512) >> 10) + 128, 0, 255);
+ v = CLIP<int>( ((r * 512) >> 10) - ((g * 429) >> 10) - ((b * 83) >> 10) + 128, 0, 255);
+}
+
+// TODO: generic YUV to RGB blit
+
+/**
+ * Blits a rectangle from one graphical format to another.
+ *
+ * @param dstbuf the buffer which will recieve the converted graphics data
+ * @param srcbuf the buffer containing the original graphics data
+ * @param dstpitch width in bytes of one full line of the dest buffer
+ * @param srcpitch width in bytes of one full line of the source buffer
+ * @param w the width of the graphics data
+ * @param h the height of the graphics data
+ * @param dstFmt the desired pixel format
+ * @param srcFmt the original pixel format
+ * @return true if conversion completes successfully,
+ * false if there is an error.
+ *
+ * @note This implementation currently arbitrarily requires that the
+ * destination's format have at least as high a bytedepth as
+ * the source's.
+ * @note This can convert a rectangle in place, if the source and
+ * destination format have the same bytedepth.
+ *
+ */
+bool crossBlit(byte *dst, const byte *src, int dstpitch, int srcpitch,
+ int w, int h, Graphics::PixelFormat dstFmt, Graphics::PixelFormat srcFmt);
+
+} // end of namespace Graphics
+
+#endif // GRAPHICS_CONVERSION_H
diff --git a/graphics/cursorman.cpp b/graphics/cursorman.cpp
index 2e71b548bc..b77aac37cf 100644
--- a/graphics/cursorman.cpp
+++ b/graphics/cursorman.cpp
@@ -57,14 +57,14 @@ bool CursorManager::showMouse(bool visible) {
return g_system->showMouse(visible);
}
-void CursorManager::pushCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor, int targetScale) {
- Cursor *cur = new Cursor(buf, w, h, hotspotX, hotspotY, keycolor, targetScale);
+void CursorManager::pushCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int targetScale, const Graphics::PixelFormat *format) {
+ Cursor *cur = new Cursor(buf, w, h, hotspotX, hotspotY, keycolor, targetScale, format);
cur->_visible = isVisible();
_cursorStack.push(cur);
if (buf) {
- g_system->setMouseCursor(cur->_data, w, h, hotspotX, hotspotY, keycolor, targetScale);
+ g_system->setMouseCursor(cur->_data, w, h, hotspotX, hotspotY, keycolor, targetScale, format);
}
}
@@ -77,7 +77,7 @@ void CursorManager::popCursor() {
if (!_cursorStack.empty()) {
cur = _cursorStack.top();
- g_system->setMouseCursor(cur->_data, cur->_width, cur->_height, cur->_hotspotX, cur->_hotspotY, cur->_keycolor, cur->_targetScale);
+ g_system->setMouseCursor(cur->_data, cur->_width, cur->_height, cur->_hotspotX, cur->_hotspotY, cur->_keycolor, cur->_targetScale, &cur->_format);
}
g_system->showMouse(isVisible());
@@ -100,15 +100,24 @@ void CursorManager::popAllCursors() {
g_system->showMouse(isVisible());
}
+void CursorManager::replaceCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int targetScale, const Graphics::PixelFormat *format) {
-void CursorManager::replaceCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor, int targetScale) {
if (_cursorStack.empty()) {
- pushCursor(buf, w, h, hotspotX, hotspotY, keycolor, targetScale);
+ pushCursor(buf, w, h, hotspotX, hotspotY, keycolor, targetScale, format);
return;
}
Cursor *cur = _cursorStack.top();
+
+#ifdef ENABLE_RGB_COLOR
+ uint size;
+ if (!format)
+ size = w * h;
+ else
+ size = w * h * format->bytesPerPixel;
+#else
uint size = w * h;
+#endif
if (cur->_size < size) {
delete[] cur->_data;
@@ -125,8 +134,14 @@ void CursorManager::replaceCursor(const byte *buf, uint w, uint h, int hotspotX,
cur->_hotspotY = hotspotY;
cur->_keycolor = keycolor;
cur->_targetScale = targetScale;
+#ifdef ENABLE_RGB_COLOR
+ if (format)
+ cur->_format = *format;
+ else
+ cur->_format = Graphics::PixelFormat::createFormatCLUT8();
+#endif
- g_system->setMouseCursor(cur->_data, w, h, hotspotX, hotspotY, keycolor, targetScale);
+ g_system->setMouseCursor(cur->_data, w, h, hotspotX, hotspotY, keycolor, targetScale, format);
}
bool CursorManager::supportsCursorPalettes() {
diff --git a/graphics/cursorman.h b/graphics/cursorman.h
index f019e37b04..ae7008f54c 100644
--- a/graphics/cursorman.h
+++ b/graphics/cursorman.h
@@ -28,6 +28,10 @@
#include "common/scummsys.h"
#include "common/stack.h"
#include "common/singleton.h"
+#include "graphics/pixelformat.h"
+#ifdef ENABLE_RGB_COLOR
+#include "common/system.h"
+#endif
namespace Graphics {
@@ -59,18 +63,19 @@ public:
* safely freed afterwards.
*
* @param buf the new cursor data
- * @param w the width
- * @param h the height
+ * @param w the width
+ * @param h the height
* @param hotspotX the hotspot X coordinate
* @param hotspotY the hotspot Y coordinate
* @param keycolor the index for the transparent color
* @param targetScale the scale for which the cursor is designed
- *
+ * @param format a pointer to the pixel format which the cursor graphic uses,
+ * CLUT8 will be used if this is NULL or not specified.
* @note It is ok for the buffer to be a NULL pointer. It is sometimes
* useful to push a "dummy" cursor and modify it later. The
* cursor will be added to the stack, but not to the backend.
*/
- void pushCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor = 255, int targetScale = 1);
+ void pushCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor = 0xFFFFFFFF, int targetScale = 1, const Graphics::PixelFormat *format = NULL);
/**
* Pop a cursor from the stack, and restore the previous one to the
@@ -90,8 +95,10 @@ public:
* @param hotspotY the hotspot Y coordinate
* @param keycolor the index for the transparent color
* @param targetScale the scale for which the cursor is designed
+ * @param format a pointer to the pixel format which the cursor graphic uses,
+ * CLUT8 will be used if this is NULL or not specified.
*/
- void replaceCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor = 255, int targetScale = 1);
+ void replaceCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor = 0xFFFFFFFF, int targetScale = 1, const Graphics::PixelFormat *format = NULL);
/**
* Pop all of the cursors and cursor palettes from their respective stacks.
@@ -166,13 +173,24 @@ private:
uint _height;
int _hotspotX;
int _hotspotY;
- byte _keycolor;
+ uint32 _keycolor;
+ Graphics::PixelFormat _format;
byte _targetScale;
uint _size;
-
- Cursor(const byte *data, uint w, uint h, int hotspotX, int hotspotY, byte keycolor = 255, int targetScale = 1) {
+ Cursor(const byte *data, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor = 0xFFFFFFFF, int targetScale = 1, const Graphics::PixelFormat *format = NULL) {
+#ifdef ENABLE_RGB_COLOR
+ if (!format)
+ _format = Graphics::PixelFormat::createFormatCLUT8();
+ else
+ _format = *format;
+ _size = w * h * _format.bytesPerPixel;
+ _keycolor &= ((1 << (_format.bytesPerPixel << 3)) - 1);
+#else
+ _format = Graphics::PixelFormat::createFormatCLUT8();
_size = w * h;
+ _keycolor &= 0xFF;
+#endif
_data = new byte[_size];
if (data && _data)
memcpy(_data, data, _size);
@@ -180,7 +198,6 @@ private:
_height = h;
_hotspotX = hotspotX;
_hotspotY = hotspotY;
- _keycolor = keycolor;
_targetScale = targetScale;
}
@@ -216,7 +233,6 @@ private:
delete[] _data;
}
};
-
Common::Stack<Cursor *> _cursorStack;
Common::Stack<Palette *> _cursorPaletteStack;
};
diff --git a/graphics/dither.cpp b/graphics/dither.cpp
index 7a92441571..e671de265e 100644
--- a/graphics/dither.cpp
+++ b/graphics/dither.cpp
@@ -23,6 +23,7 @@
*/
#include "common/endian.h"
+#include "graphics/conversion.h"
#include "graphics/dither.h"
namespace Graphics {
diff --git a/graphics/dither.h b/graphics/dither.h
index e6d606cdd4..18f98ce4e0 100644
--- a/graphics/dither.h
+++ b/graphics/dither.h
@@ -43,19 +43,6 @@ public:
kPaletteYUV //!< Palette in YUV colorspace
};
- /** Converting a color from YUV to RGB colorspace. */
- inline static void YUV2RGB(byte y, byte u, byte v, byte &r, byte &g, byte &b) {
- r = CLIP<int>(y + ((1357 * (v - 128)) >> 10), 0, 255);
- g = CLIP<int>(y - (( 691 * (v - 128)) >> 10) - ((333 * (u - 128)) >> 10), 0, 255);
- b = CLIP<int>(y + ((1715 * (u - 128)) >> 10), 0, 255);
- }
- /** Converting a color from RGB to YUV colorspace. */
- inline static void RGB2YUV(byte r, byte g, byte b, byte &y, byte &u, byte &v) {
- y = CLIP<int>( ((r * 306) >> 10) + ((g * 601) >> 10) + ((b * 117) >> 10) , 0, 255);
- u = CLIP<int>(-((r * 172) >> 10) - ((g * 340) >> 10) + ((b * 512) >> 10) + 128, 0, 255);
- v = CLIP<int>( ((r * 512) >> 10) - ((g * 429) >> 10) - ((b * 83) >> 10) + 128, 0, 255);
- }
-
/** Create a lookup table of a given depth and palette format.
*
* @param depth How many bits of each color component to consider.
diff --git a/graphics/jpeg.cpp b/graphics/jpeg.cpp
new file mode 100644
index 0000000000..0ad2cf7699
--- /dev/null
+++ b/graphics/jpeg.cpp
@@ -0,0 +1,638 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "graphics/jpeg.h"
+
+#include "common/endian.h"
+#include "common/util.h"
+
+namespace Graphics {
+
+// Order used to traverse the quantization tables
+uint8 JPEG::_zigZagOrder[64] = {
+ 0, 1, 8, 16, 9, 2, 3, 10,
+ 17, 24, 32, 25, 18, 11, 4, 5,
+ 12, 19, 26, 33, 40, 48, 41, 34,
+ 27, 20, 13, 6, 7, 14, 21, 28,
+ 35, 42, 49, 56, 57, 50, 43, 36,
+ 29, 22, 15, 23, 30, 37, 44, 51,
+ 58, 59, 52, 45, 38, 31, 39, 46,
+ 53, 60, 61, 54, 47, 55, 62, 63
+};
+
+JPEG::JPEG() :
+ _str(NULL), _w(0), _h(0), _numComp(0), _components(NULL), _numScanComp(0),
+ _scanComp(NULL), _currentComp(NULL) {
+
+ // Initialize the quantization tables
+ for (int i = 0; i < JPEG_MAX_QUANT_TABLES; i++)
+ _quant[i] = NULL;
+
+ // Initialize the Huffman tables
+ for (int i = 0; i < 2 * JPEG_MAX_HUFF_TABLES; i++) {
+ _huff[i].count = 0;
+ _huff[i].values = NULL;
+ _huff[i].sizes = NULL;
+ _huff[i].codes = NULL;
+ }
+}
+
+JPEG::~JPEG() {
+ reset();
+}
+
+void JPEG::reset() {
+ // Reset member variables
+ _str = NULL;
+ _w = _h = 0;
+
+ // Free the components
+ for (int c = 0; c < _numComp; c++)
+ _components[c].surface.free();
+ delete[] _components; _components = NULL;
+ _numComp = 0;
+
+ // Free the scan components
+ delete[] _scanComp; _scanComp = NULL;
+ _numScanComp = 0;
+ _currentComp = NULL;
+
+ // Free the quantization tables
+ for (int i = 0; i < JPEG_MAX_QUANT_TABLES; i++) {
+ delete[] _quant[i];
+ _quant[i] = NULL;
+ }
+
+ // Free the Huffman tables
+ for (int i = 0; i < 2 * JPEG_MAX_HUFF_TABLES; i++) {
+ _huff[i].count = 0;
+ delete[] _huff[i].values; _huff[i].values = NULL;
+ delete[] _huff[i].sizes; _huff[i].sizes = NULL;
+ delete[] _huff[i].codes; _huff[i].codes = NULL;
+ }
+}
+
+bool JPEG::read(Common::SeekableReadStream *str) {
+ // Reset member variables and tables from previous reads
+ reset();
+
+ // Save the input stream
+ _str = str;
+
+ bool ok = true;
+ bool done = false;
+ while (!_str->eos() && ok && !done) {
+ // Read the marker
+ uint16 marker = _str->readByte();
+ if (marker != 0xFF) {
+ error("JPEG: Invalid marker[0]: 0x%02X", marker);
+ ok = false;
+ break;
+ }
+
+ while (marker == 0xFF)
+ marker = _str->readByte();
+
+ // Process the marker data
+ switch (marker) {
+ case 0xC0: // Start Of Frame
+ ok = readSOF0();
+ break;
+ case 0xC4: // Define Huffman Tables
+ ok = readDHT();
+ break;
+ case 0xD8: // Start Of Image
+ break;
+ case 0xD9: // End Of Image
+ done = true;
+ break;
+ case 0xDA: // Start Of Scan
+ ok = readSOS();
+ break;
+ case 0xDB: // Define Quantization Tables
+ ok = readDQT();
+ break;
+ case 0xE0: // JFIF/JFXX segment
+ ok = readJFIF();
+ break;
+ case 0xFE: // Comment
+ _str->seek(_str->readUint16BE() - 2, SEEK_CUR);
+ break;
+ default: { // Unknown marker
+ uint16 size = _str->readUint16BE();
+ warning("JPEG: Unknown marker %02X, skipping %d bytes", marker, size - 2);
+ _str->seek(size - 2, SEEK_CUR);
+ }
+ }
+ }
+ return ok;
+}
+
+bool JPEG::readJFIF() {
+ /* uint16 length = */ _str->readUint16BE();
+ uint32 tag = _str->readUint32BE();
+ if (tag != MKID_BE('JFIF'))
+ return false;
+ _str->readByte(); // NULL
+ /* byte majorVersion = */ _str->readByte();
+ /* byte minorVersion = */ _str->readByte();
+ /* byte densityUnits = */ _str->readByte();
+ /* uint16 xDensity = */ _str->readUint16BE();
+ /* uint16 yDensity = */ _str->readUint16BE();
+ byte thumbW = _str->readByte();
+ byte thumbH = _str->readByte();
+ _str->seek(thumbW * thumbH * 3, SEEK_CUR); // Ignore thumbnail
+ return true;
+}
+
+// Marker 0xC0 (Start Of Frame, Baseline DCT)
+bool JPEG::readSOF0() {
+ debug(5, "JPEG: readSOF0");
+ uint16 size = _str->readUint16BE();
+
+ // Read the sample precision
+ uint8 precision = _str->readByte();
+ if (precision != 8) {
+ warning("JPEG: Just 8 bit precision supported at the moment");
+ return false;
+ }
+
+ // Image size
+ _h = _str->readUint16BE();
+ _w = _str->readUint16BE();
+
+ // Number of components
+ _numComp = _str->readByte();
+ if (size != 8 + 3 * _numComp) {
+ warning("JPEG: Invalid number of components");
+ return false;
+ }
+
+ // Allocate the new components
+ delete[] _components;
+ _components = new Component[_numComp];
+
+ // Read the components details
+ for (int c = 0; c < _numComp; c++) {
+ _components[c].id = _str->readByte();
+ _components[c].factorH = _str->readByte();
+ _components[c].factorV = _components[c].factorH & 0xF;
+ _components[c].factorH >>= 4;
+ _components[c].quantTableSelector = _str->readByte();
+ }
+
+ return true;
+}
+
+// Marker 0xC4 (Define Huffman Tables)
+bool JPEG::readDHT() {
+ debug(5, "JPEG: readDHT");
+ uint16 size = _str->readUint16BE() - 2;
+ uint32 pos = _str->pos();
+
+ while ((uint32)_str->pos() < (size + pos)) {
+ // Read the table type and id
+ uint8 tableId = _str->readByte();
+ uint8 tableType = tableId >> 4; // type 0: DC, 1: AC
+ tableId &= 0xF;
+ uint8 tableNum = (tableId << 1) + tableType;
+
+ // Free the Huffman table
+ delete[] _huff[tableNum].values; _huff[tableNum].values = NULL;
+ delete[] _huff[tableNum].sizes; _huff[tableNum].sizes = NULL;
+ delete[] _huff[tableNum].codes; _huff[tableNum].codes = NULL;
+
+ // Read the number of values for each length
+ uint8 numValues[16];
+ _huff[tableNum].count = 0;
+ for (int len = 0; len < 16; len++) {
+ numValues[len] = _str->readByte();
+ _huff[tableNum].count += numValues[len];
+ }
+
+ // Allocate memory for the current table
+ _huff[tableNum].values = new uint8[_huff[tableNum].count];
+ _huff[tableNum].sizes = new uint8[_huff[tableNum].count];
+ _huff[tableNum].codes = new uint16[_huff[tableNum].count];
+
+ // Read the table contents
+ int cur = 0;
+ for (int len = 0; len < 16; len++) {
+ for (int i = 0; i < numValues[len]; i++) {
+ _huff[tableNum].values[cur] = _str->readByte();
+ _huff[tableNum].sizes[cur] = len + 1;
+ cur++;
+ }
+ }
+
+ // Fill the table of Huffman codes
+ cur = 0;
+ uint16 curCode = 0;
+ uint8 curCodeSize = _huff[tableNum].sizes[0];
+ while (cur < _huff[tableNum].count) {
+ // Increase the code size to fit the request
+ while (_huff[tableNum].sizes[cur] != curCodeSize) {
+ curCode <<= 1;
+ curCodeSize++;
+ }
+
+ // Assign the current code
+ _huff[tableNum].codes[cur] = curCode;
+ curCode++;
+ cur++;
+ }
+ }
+
+ return true;
+}
+
+// Marker 0xDA (Start Of Scan)
+bool JPEG::readSOS() {
+ debug(5, "JPEG: readSOS");
+ uint16 size = _str->readUint16BE();
+
+ // Number of scan components
+ _numScanComp = _str->readByte();
+ if (size != 6 + 2 * _numScanComp) {
+ warning("JPEG: Invalid number of components");
+ return false;
+ }
+
+ // Allocate the new scan components
+ delete[] _scanComp;
+ _scanComp = new Component *[_numScanComp];
+
+ // Reset the maximum sampling factors
+ _maxFactorV = 0;
+ _maxFactorH = 0;
+
+ // Component-specification parameters
+ for (int c = 0; c < _numScanComp; c++) {
+ // Read the desired component id
+ uint8 id = _str->readByte();
+
+ // Search the component with the specified id
+ bool found = false;
+ for (int i = 0; !found && i < _numComp; i++) {
+ if (_components[i].id == id) {
+ // We found the desired component
+ found = true;
+
+ // Assign the found component to the c'th scan component
+ _scanComp[c] = &_components[i];
+ }
+ }
+
+ if (!found) {
+ warning("JPEG: Invalid component");
+ return false;
+ }
+
+ // Read the entropy table selectors
+ _scanComp[c]->DCentropyTableSelector = _str->readByte();
+ _scanComp[c]->ACentropyTableSelector = _scanComp[c]->DCentropyTableSelector & 0xF;
+ _scanComp[c]->DCentropyTableSelector >>= 4;
+
+ // Calculate the maximum sampling factors
+ if (_scanComp[c]->factorV > _maxFactorV)
+ _maxFactorV = _scanComp[c]->factorV;
+
+ if (_scanComp[c]->factorH > _maxFactorH)
+ _maxFactorH = _scanComp[c]->factorH;
+
+ // Initialize the DC predictor
+ _scanComp[c]->DCpredictor = 0;
+ }
+
+ // Initialize the scan surfaces
+ for (int c = 0; c < _numScanComp; c++)
+ _scanComp[c]->surface.create(_w, _h, 1);
+
+ // Start of spectral selection
+ if (_str->readByte() != 0) {
+ warning("JPEG: Progressive scanning not supported");
+ return false;
+ }
+
+ // End of spectral selection
+ if (_str->readByte() != 63) {
+ warning("JPEG: Progressive scanning not supported");
+ return false;
+ }
+
+ // Successive approximation parameters
+ if (_str->readByte() != 0) {
+ warning("JPEG: Progressive scanning not supported");
+ return false;
+ }
+
+ // Entropy coded sequence starts, initialize Huffman decoder
+ _bitsNumber = 0;
+
+ // Read all the scan MCUs
+ uint16 xMCU = _w / (_maxFactorH * 8);
+ uint16 yMCU = _h / (_maxFactorV * 8);
+
+ // Check for non- multiple-of-8 dimensions
+ if (_w % 8 != 0)
+ xMCU++;
+ if (_h % 8 != 0)
+ yMCU++;
+
+ bool ok = true;
+ for (int y = 0; ok && (y < yMCU); y++)
+ for (int x = 0; ok && (x < xMCU); x++)
+ ok = readMCU(x, y);
+
+ return ok;
+}
+
+// Marker 0xDB (Define Quantization Tables)
+bool JPEG::readDQT() {
+ debug(5, "JPEG: readDQT");
+ uint16 size = _str->readUint16BE() - 2;
+ uint32 pos = _str->pos();
+
+ while ((uint32)_str->pos() < (pos + size)) {
+ // Read the table precision and id
+ uint8 tableId = _str->readByte();
+ bool highPrecision = (tableId & 0xF0) != 0;
+
+ // Validate the table id
+ tableId &= 0xF;
+ if (tableId > JPEG_MAX_QUANT_TABLES) {
+ warning("JPEG: Invalid number of components");
+ return false;
+ }
+
+ // Create the new table if necessary
+ if (!_quant[tableId])
+ _quant[tableId] = new uint16[64];
+
+ // Read the table (stored in Zig-Zag order)
+ for (int i = 0; i < 64; i++)
+ _quant[tableId][i] = highPrecision ? _str->readUint16BE() : _str->readByte();
+ }
+
+ return true;
+}
+
+bool JPEG::readMCU(uint16 xMCU, uint16 yMCU) {
+ bool ok = true;
+ for (int c = 0; ok && (c < _numComp); c++) {
+ // Set the current component
+ _currentComp = _scanComp[c];
+
+ // Read the data units of the current component
+ for (int y = 0; ok && (y < _scanComp[c]->factorV); y++)
+ for (int x = 0; ok && (x < _scanComp[c]->factorH); x++)
+ ok = readDataUnit(xMCU * _scanComp[c]->factorH + x, yMCU * _scanComp[c]->factorV + y);
+ }
+
+ return ok;
+}
+
+float JPEG::idct(int x, int y, int weight, int fx, int fy) {
+ float vx = cos((2 * x + 1) * fx * PI / 16);
+ float vy = cos((2 * y + 1) * fy * PI / 16);
+ float ret = (float)weight * vx * vy;
+
+ if (fx == 0)
+ ret /= sqrt(2.0f);
+
+ if (fy == 0)
+ ret /= sqrt(2.0f);
+
+ return ret;
+}
+
+bool JPEG::readDataUnit(uint16 x, uint16 y) {
+ // Prepare an empty data array
+ int16 readData[64];
+ for (int i = 1; i < 64; i++)
+ readData[i] = 0;
+
+ // Read the DC component
+ readData[0] = _currentComp->DCpredictor + readDC();
+ _currentComp->DCpredictor = readData[0];
+
+ // Read the AC components (stored in Zig-Zag)
+ readAC(readData);
+
+ // Calculate the DCT coefficients from the input sequence
+ int16 DCT[64];
+ for (int i = 0; i < 64; i++) {
+ // Dequantize
+ int16 val = readData[i];
+ int16 quant = _quant[_currentComp->quantTableSelector][i];
+ val *= quant;
+
+ // Store the normalized coefficients, undoing the Zig-Zag
+ DCT[_zigZagOrder[i]] = val;
+ }
+
+ // Shortcut the IDCT for DC component
+ float result[64];
+ for (int i = 0; i < 64; i++)
+ result[i] = DCT[0] / 2;
+
+ // Apply the IDCT (PAG31)
+ for (int i = 1; i < 64; i++) {
+ if (DCT[i])
+ for (int _y = 0; _y < 8; _y++)
+ for (int _x = 0; _x < 8; _x++)
+ result[_y * 8 + _x] += idct(_x, _y, DCT[i], i % 8, i / 8);
+ }
+
+ // Level shift to make the values unsigned
+ // Divide by 4 is final part of IDCT
+ for (int i = 0; i < 64; i++) {
+ result[i] = result[i] / 4 + 128;
+
+ if (result[i] < 0)
+ result[i] = 0;
+
+ if (result[i] > 255)
+ result[i] = 255;
+ }
+
+ // Paint the component surface
+ uint8 scalingV = _maxFactorV / _currentComp->factorV;
+ uint8 scalingH = _maxFactorH / _currentComp->factorH;
+
+ // Convert coordinates from MCU blocks to pixels
+ x <<= 3;
+ y <<= 3;
+
+ // Handle non- multiple-of-8 dimensions
+ byte xLim = 8;
+ byte yLim = 8;
+ if (x*scalingH + 8 > _w)
+ xLim -= (x*scalingH + 8 - _w);
+ if (y*scalingV + 8 > _h)
+ yLim -= (y*scalingV + 8 - _h);
+
+ for (int j = 0; j < yLim; j++) {
+ for (int sV = 0; sV < scalingV; sV++) {
+ // Get the beginning of the block line
+ byte *ptr = (byte *)_currentComp->surface.getBasePtr(x * scalingH, (y + j) * scalingV + sV);
+
+ for (int i = 0; i < xLim; i++) {
+ for (uint8 sH = 0; sH < scalingH; sH++) {
+ *ptr = (byte)(result[j * 8 + i]);
+ ptr++;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+int16 JPEG::readDC() {
+ // DC is type 0
+ uint8 tableNum = _currentComp->DCentropyTableSelector << 1;
+
+ // Get the number of bits to read
+ uint8 numBits = readHuff(tableNum);
+
+ // Read the requested bits
+ return readSignedBits(numBits);
+}
+
+void JPEG::readAC(int16 *out) {
+ // AC is type 1
+ uint8 tableNum = (_currentComp->ACentropyTableSelector << 1) + 1;
+
+ // Start reading AC element 1
+ uint8 cur = 1;
+ while (cur < 64) {
+ uint8 s = readHuff(tableNum);
+ uint8 r = s >> 4;
+ s &= 0xF;
+
+ if (s == 0) {
+ if (r == 15) {
+ // Skip 16 values
+ cur += 16;
+ } else {
+ // EOB: end of block
+ cur = 64;
+ }
+ } else {
+ // Skip r values
+ cur += r;
+
+ // Read the next value
+ out[cur] = readSignedBits(s);
+ cur++;
+ }
+ }
+}
+
+int16 JPEG::readSignedBits(uint8 numBits) {
+ uint16 ret = 0;
+ if (numBits > 16) error("requested %d bits", numBits); //XXX
+
+ // MSB=0 for negatives, 1 for positives
+ for (int i = 0; i < numBits; i++)
+ ret = (ret << 1) + readBit();
+
+ // Extend sign bits (PAG109)
+ if (!(ret >> (numBits - 1)))
+ {
+ uint16 tmp = ((uint16)-1 << numBits) + 1;
+ ret = ret + tmp;
+ }
+ return ret;
+}
+
+// TODO: optimize?
+uint8 JPEG::readHuff(uint8 table) {
+ bool foundCode = false;
+ uint8 val = 0;
+
+ uint8 cur = 0;
+ uint8 codeSize = 1;
+ uint16 code = readBit();
+ while (!foundCode) {
+ // Prepare a code of the current size
+ while (codeSize < _huff[table].sizes[cur]) {
+ code = (code << 1) + readBit();
+ codeSize++;
+ }
+
+ // Compare the codes of the current size
+ while (!foundCode && (codeSize == _huff[table].sizes[cur])) {
+ if (code == _huff[table].codes[cur]) {
+ // Found the code
+ val = _huff[table].values[cur];
+ foundCode = true;
+ } else {
+ // Continue reading
+ cur++;
+ }
+ }
+ }
+
+ return val;
+}
+
+uint8 JPEG::readBit() {
+ // Read a whole byte if necessary
+ if (_bitsNumber == 0) {
+ _bitsData = _str->readByte();
+ _bitsNumber = 8;
+
+ // Detect markers
+ if (_bitsData == 0xFF) {
+ uint8 byte2 = _str->readByte();
+
+ // A stuffed 0 validates the previous byte
+ if (byte2 != 0) {
+ if (byte2 == 0xDC) {
+ // DNL marker: Define Number of Lines
+ // TODO: terminate scan
+ printf("DNL marker detected: terminate scan\n");
+ } else {
+ printf("Error: marker 0x%02X read in entropy data\n", byte2);
+ }
+ }
+ }
+ }
+ _bitsNumber--;
+
+ return (_bitsData & (1 << _bitsNumber)) ? 1 : 0;
+}
+
+Surface *JPEG::getComponent(uint c) {
+ for (int i = 0; i < _numComp; i++)
+ if (_components[i].id == c) // We found the desired component
+ return &_components[i].surface;
+
+ return NULL;
+}
+
+} // End of Graphics namespace
diff --git a/graphics/jpeg.h b/graphics/jpeg.h
new file mode 100644
index 0000000000..f4743a5e83
--- /dev/null
+++ b/graphics/jpeg.h
@@ -0,0 +1,118 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GRAPHICS_JPEG_H
+#define GRAPHICS_JPEG_H
+
+#include "common/stream.h"
+#include "graphics/surface.h"
+
+namespace Graphics {
+
+#define JPEG_MAX_QUANT_TABLES 4
+#define JPEG_MAX_HUFF_TABLES 2
+
+class JPEG {
+public:
+ JPEG();
+ ~JPEG();
+
+ bool read(Common::SeekableReadStream *str);
+ Surface *getComponent(uint c);
+
+private:
+ void reset();
+
+ Common::SeekableReadStream *_str;
+ uint16 _w, _h;
+
+ // Image components
+ uint8 _numComp;
+ struct Component {
+ // Global values
+ uint8 id;
+ uint8 factorH;
+ uint8 factorV;
+ uint8 quantTableSelector;
+
+ // Scan specific values
+ uint8 DCentropyTableSelector;
+ uint8 ACentropyTableSelector;
+ int16 DCpredictor;
+
+ // Result image for this component
+ Surface surface;
+ } *_components;
+
+ // Scan components
+ uint8 _numScanComp;
+ Component **_scanComp;
+ Component *_currentComp;
+
+ // Maximum sampling factors, used to calculate the interleaving of the MCU
+ uint8 _maxFactorV;
+ uint8 _maxFactorH;
+
+ // Zig-Zag order
+ static uint8 _zigZagOrder[64];
+
+ // Quantization tables
+ uint16 *_quant[JPEG_MAX_QUANT_TABLES];
+
+ // Huffman tables
+ struct HuffmanTable {
+ uint8 count;
+ uint8 *values;
+ uint8 *sizes;
+ uint16 *codes;
+ } _huff[2 * JPEG_MAX_HUFF_TABLES];
+
+ // Marker read functions
+ bool readJFIF();
+ bool readSOF0();
+ bool readDHT();
+ bool readSOS();
+ bool readDQT();
+
+ // Helper functions
+ bool readMCU(uint16 xMCU, uint16 yMCU);
+ bool readDataUnit(uint16 x, uint16 y);
+ int16 readDC();
+ void readAC(int16 *out);
+ int16 readSignedBits(uint8 numBits);
+
+ // Huffman decoding
+ uint8 readHuff(uint8 table);
+ uint8 readBit();
+ uint8 _bitsData;
+ uint8 _bitsNumber;
+
+ // Discrete Cosine Transformation
+ float idct(int x, int y, int weight, int fx, int fy);
+};
+
+} // End of Graphics namespace
+
+#endif // GRAPHICS_JPEG_H
diff --git a/graphics/module.mk b/graphics/module.mk
index 46ed564e1e..ed14051243 100644
--- a/graphics/module.mk
+++ b/graphics/module.mk
@@ -1,6 +1,7 @@
MODULE := graphics
MODULE_OBJS := \
+ conversion.o \
cursorman.o \
dither.o \
font.o \
@@ -11,6 +12,7 @@ MODULE_OBJS := \
fonts/scummfont.o \
iff.o \
imagedec.o \
+ jpeg.o \
primitives.o \
scaler.o \
scaler/thumbnail_intern.o \
diff --git a/graphics/pixelformat.h b/graphics/pixelformat.h
index f59650e5cc..d16de51ea7 100644
--- a/graphics/pixelformat.h
+++ b/graphics/pixelformat.h
@@ -27,6 +27,7 @@
#define GRAPHICS_PIXELFORMAT_H
#include "common/scummsys.h"
+#include "common/list.h"
namespace Graphics {
@@ -50,6 +51,24 @@ struct PixelFormat {
byte rLoss, gLoss, bLoss, aLoss; /**< Precision loss of each color component. */
byte rShift, gShift, bShift, aShift; /**< Binary left shift of each color component in the pixel value. */
+ inline PixelFormat() {
+ bytesPerPixel =
+ rLoss = gLoss = bLoss = aLoss =
+ rShift = gShift = bShift = aShift = 0;
+ }
+
+ inline PixelFormat(byte BytesPerPixel,
+ byte RBits, byte GBits, byte BBits, byte ABits,
+ byte RShift, byte GShift, byte BShift, byte AShift) {
+ bytesPerPixel = BytesPerPixel;
+ rLoss = 8 - RBits, gLoss = 8 - GBits, bLoss = 8 - BBits, aLoss = 8 - ABits;
+ rShift = RShift, gShift = GShift, bShift = BShift, aShift = AShift;
+ }
+
+ static inline PixelFormat createFormatCLUT8() {
+ return PixelFormat(1, 0, 0, 0, 0, 0, 0, 0, 0);
+ }
+
inline bool operator==(const PixelFormat &fmt) const {
// TODO: If aLoss==8, then the value of aShift is irrelevant, and should be ignored.
return 0 == memcmp(this, &fmt, sizeof(PixelFormat));
@@ -129,6 +148,26 @@ struct PixelFormat {
}
};
+/**
+ * Determines the first matching format between two lists.
+ *
+ * @param backend The higher priority list, meant to be a list of formats supported by the backend
+ * @param frontend The lower priority list, meant to be a list of formats supported by the engine
+ * @return The first item on the backend list that also occurs on the frontend list
+ * or PixelFormat::createFormatCLUT8() if no matching formats were found.
+ */
+inline PixelFormat findCompatibleFormat(Common::List<PixelFormat> backend, Common::List<PixelFormat> frontend) {
+#ifdef ENABLE_RGB_COLOR
+ for (Common::List<PixelFormat>::iterator i = backend.begin(); i != backend.end(); ++i) {
+ for (Common::List<PixelFormat>::iterator j = frontend.begin(); j != frontend.end(); ++j) {
+ if (*i == *j)
+ return *i;
+ }
+ }
+#endif
+ return PixelFormat::createFormatCLUT8();
+}
+
} // end of namespace Graphics
#endif
diff --git a/graphics/scaler.cpp b/graphics/scaler.cpp
index a3aaaa121d..8c677cc083 100644
--- a/graphics/scaler.cpp
+++ b/graphics/scaler.cpp
@@ -30,18 +30,17 @@
int gBitFormat = 565;
-static const Graphics::PixelFormat gPixelFormat555 = {
+static const Graphics::PixelFormat gPixelFormat555(
2,
3, 3, 3, 8,
10, 5, 0, 0
- };
+ );
-static const Graphics::PixelFormat gPixelFormat565 = {
+static const Graphics::PixelFormat gPixelFormat565(
2,
3, 2, 3, 8,
11, 5, 0, 0
- };
-
+ );
#ifndef DISABLE_HQ_SCALERS
diff --git a/graphics/scaler/thumbnail_intern.cpp b/graphics/scaler/thumbnail_intern.cpp
index fabe07b031..a542fe2268 100644
--- a/graphics/scaler/thumbnail_intern.cpp
+++ b/graphics/scaler/thumbnail_intern.cpp
@@ -23,6 +23,7 @@
*
*/
+#include "common/endian.h"
#include "common/scummsys.h"
#include "common/system.h"
@@ -98,7 +99,8 @@ static bool grabScreen565(Graphics::Surface *surf) {
if (!screen)
return false;
- assert(screen->bytesPerPixel == 1 && screen->pixels != 0);
+ assert(screen->bytesPerPixel == 1 || screen->bytesPerPixel == 2);
+ assert(screen->pixels != 0);
byte palette[256 * 4];
g_system->grabPalette(&palette[0], 0, 256);
@@ -107,11 +109,17 @@ static bool grabScreen565(Graphics::Surface *surf) {
for (uint y = 0; y < screen->h; ++y) {
for (uint x = 0; x < screen->w; ++x) {
- byte r, g, b;
- r = palette[((uint8*)screen->pixels)[y * screen->pitch + x] * 4];
- g = palette[((uint8*)screen->pixels)[y * screen->pitch + x] * 4 + 1];
- b = palette[((uint8*)screen->pixels)[y * screen->pitch + x] * 4 + 2];
-
+ byte r, g, b;
+ if (screen->bytesPerPixel == 2) {
+ uint16 col = READ_UINT16(screen->getBasePtr(x, y));
+ r = ((col >> 10) & 0x1F) << 3;
+ g = ((col >> 5) & 0x1F) << 3;
+ b = ((col >> 0) & 0x1F) << 3;
+ } else {
+ r = palette[((uint8*)screen->pixels)[y * screen->pitch + x] * 4];
+ g = palette[((uint8*)screen->pixels)[y * screen->pitch + x] * 4 + 1];
+ b = palette[((uint8*)screen->pixels)[y * screen->pitch + x] * 4 + 2];
+ }
((uint16*)surf->pixels)[y * surf->w + x] = Graphics::RGBToColor<Graphics::ColorMasks<565> >(r, g, b);
}
}
diff --git a/graphics/video/coktelvideo/coktelvideo.cpp b/graphics/video/coktelvideo/coktelvideo.cpp
index 39aeca07bd..063ad190e6 100644
--- a/graphics/video/coktelvideo/coktelvideo.cpp
+++ b/graphics/video/coktelvideo/coktelvideo.cpp
@@ -26,6 +26,7 @@
#include "common/endian.h"
#include "common/system.h"
+#include "graphics/conversion.h"
#include "graphics/dither.h"
#include "graphics/video/coktelvideo/coktelvideo.h"
#include "graphics/video/coktelvideo/indeo3.h"
@@ -1915,7 +1916,7 @@ void Vmd::blit16(byte *dest, byte *src, int16 srcPitch, int16 width, int16 heigh
byte b = ((data & 0x001F) >> 0);
byte dY, dU, dV;
- Graphics::PaletteLUT::RGB2YUV(r << 3, g << 3, b << 3, dY, dU, dV);
+ Graphics::RGB2YUV(r << 3, g << 3, b << 3, dY, dU, dV);
byte p = dither->dither(dY, dU, dV, j);
@@ -1949,7 +1950,7 @@ void Vmd::blit24(byte *dest, byte *src, int16 srcPitch, int16 width, int16 heigh
byte b = s[0];
byte dY, dU, dV;
- Graphics::PaletteLUT::RGB2YUV(r, g, b, dY, dU, dV);
+ Graphics::RGB2YUV(r, g, b, dY, dU, dV);
byte p = dither->dither(dY, dU, dV, j);