aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Hoops2014-08-23 09:49:35 -0400
committerMatthew Hoops2015-04-11 14:36:42 -0400
commite5048ecffed49eb0ddb6b69488cfeebbc3820d8f (patch)
treed2cb820fc9fca06e70c4a5c6cef41d3a2f9b24a4
parentf342d63431fc0784adc08648f17a6bbad934743f (diff)
downloadscummvm-rg350-e5048ecffed49eb0ddb6b69488cfeebbc3820d8f.tar.gz
scummvm-rg350-e5048ecffed49eb0ddb6b69488cfeebbc3820d8f.tar.bz2
scummvm-rg350-e5048ecffed49eb0ddb6b69488cfeebbc3820d8f.zip
IMAGE: Rewrite a bunch of Cinepak using templates
-rw-r--r--image/codecs/cinepak.cpp555
-rw-r--r--image/codecs/cinepak.h3
2 files changed, 291 insertions, 267 deletions
diff --git a/image/codecs/cinepak.cpp b/image/codecs/cinepak.cpp
index de5198812b..f43c952c2c 100644
--- a/image/codecs/cinepak.cpp
+++ b/image/codecs/cinepak.cpp
@@ -35,18 +35,290 @@
namespace Image {
-#define PUT_PIXEL(offset, lum, u, v) \
- if (_pixelFormat.bytesPerPixel != 1) { \
- byte r = _clipTable[lum + (v << 1)]; \
- byte g = _clipTable[lum - (u >> 1) - v]; \
- byte b = _clipTable[lum + (u << 1)]; \
- \
- if (_pixelFormat.bytesPerPixel == 2) \
- *((uint16 *)_curFrame.surface->getPixels() + offset) = _pixelFormat.RGBToColor(r, g, b); \
- else \
- *((uint32 *)_curFrame.surface->getPixels() + offset) = _pixelFormat.RGBToColor(r, g, b); \
- } else \
- *((byte *)_curFrame.surface->getPixels() + offset) = lum
+namespace {
+
+inline void convertYUVToRGB(const byte *clipTable, byte y, int8 u, int8 v, byte &r, byte &g, byte &b) {
+ r = clipTable[y + (v << 1)];
+ g = clipTable[y - (u >> 1) - v];
+ b = clipTable[y + (u << 1)];
+}
+
+inline uint32 convertYUVToColor(const byte *clipTable, const Graphics::PixelFormat &format, byte y, byte u, byte v) {
+ byte r, g, b;
+ convertYUVToRGB(clipTable, y, u, v, r, g, b);
+ return format.RGBToColor(r, g, b);
+}
+
+inline uint16 createDitherTableIndex(const byte *clipTable, byte y, int8 u, int8 v) {
+ byte r, g, b;
+ convertYUVToRGB(clipTable, y, u, v, r, g, b);
+ return ((r & 0xF8) << 6) |
+ ((g & 0xF8) << 1) |
+ ((b & 0xF0) >> 4);
+}
+
+/**
+ * Put a raw pixel to the destination surface
+ */
+template<typename PixelInt>
+inline void putPixelRaw(PixelInt *dst, const byte *clipTable, const Graphics::PixelFormat &format, byte y, byte u, byte v) {
+ *dst = convertYUVToColor(clipTable, format, y, u, v);
+}
+
+/**
+ * Specialized putPixelRaw for palettized 8bpp output
+ */
+template<>
+inline void putPixelRaw(byte *dst, const byte *clipTable, const Graphics::PixelFormat &format, byte y, byte u, byte v) {
+ *dst = y;
+}
+
+/**
+ * The default codebook converter: raw output.
+ */
+struct CodebookConverterRaw {
+ template<typename PixelInt>
+ static inline void decodeBlock1(byte codebookIndex, const CinepakStrip &strip, PixelInt *(&rows)[4], const byte *clipTable, const byte *colorMap, const Graphics::PixelFormat &format) {
+ const CinepakCodebook &codebook = strip.v1_codebook[codebookIndex];
+ putPixelRaw(rows[0] + 0, clipTable, format, codebook.y[0], codebook.u, codebook.v);
+ putPixelRaw(rows[0] + 1, clipTable, format, codebook.y[0], codebook.u, codebook.v);
+ putPixelRaw(rows[1] + 0, clipTable, format, codebook.y[0], codebook.u, codebook.v);
+ putPixelRaw(rows[1] + 1, clipTable, format, codebook.y[0], codebook.u, codebook.v);
+
+ putPixelRaw(rows[0] + 2, clipTable, format, codebook.y[1], codebook.u, codebook.v);
+ putPixelRaw(rows[0] + 3, clipTable, format, codebook.y[1], codebook.u, codebook.v);
+ putPixelRaw(rows[1] + 2, clipTable, format, codebook.y[1], codebook.u, codebook.v);
+ putPixelRaw(rows[1] + 3, clipTable, format, codebook.y[1], codebook.u, codebook.v);
+
+ putPixelRaw(rows[2] + 0, clipTable, format, codebook.y[2], codebook.u, codebook.v);
+ putPixelRaw(rows[2] + 1, clipTable, format, codebook.y[2], codebook.u, codebook.v);
+ putPixelRaw(rows[3] + 0, clipTable, format, codebook.y[2], codebook.u, codebook.v);
+ putPixelRaw(rows[3] + 1, clipTable, format, codebook.y[2], codebook.u, codebook.v);
+
+ putPixelRaw(rows[2] + 2, clipTable, format, codebook.y[3], codebook.u, codebook.v);
+ putPixelRaw(rows[2] + 3, clipTable, format, codebook.y[3], codebook.u, codebook.v);
+ putPixelRaw(rows[3] + 2, clipTable, format, codebook.y[3], codebook.u, codebook.v);
+ putPixelRaw(rows[3] + 3, clipTable, format, codebook.y[3], codebook.u, codebook.v);
+ }
+
+ template<typename PixelInt>
+ static inline void decodeBlock4(const byte (&codebookIndex)[4], const CinepakStrip &strip, PixelInt *(&rows)[4], const byte *clipTable, const byte *colorMap, const Graphics::PixelFormat &format) {
+ const CinepakCodebook &codebook1 = strip.v4_codebook[codebookIndex[0]];
+ putPixelRaw(rows[0] + 0, clipTable, format, codebook1.y[0], codebook1.u, codebook1.v);
+ putPixelRaw(rows[0] + 1, clipTable, format, codebook1.y[1], codebook1.u, codebook1.v);
+ putPixelRaw(rows[1] + 0, clipTable, format, codebook1.y[2], codebook1.u, codebook1.v);
+ putPixelRaw(rows[1] + 1, clipTable, format, codebook1.y[3], codebook1.u, codebook1.v);
+
+ const CinepakCodebook &codebook2 = strip.v4_codebook[codebookIndex[1]];
+ putPixelRaw(rows[0] + 2, clipTable, format, codebook2.y[0], codebook2.u, codebook2.v);
+ putPixelRaw(rows[0] + 3, clipTable, format, codebook2.y[1], codebook2.u, codebook2.v);
+ putPixelRaw(rows[1] + 2, clipTable, format, codebook2.y[2], codebook2.u, codebook2.v);
+ putPixelRaw(rows[1] + 3, clipTable, format, codebook2.y[3], codebook2.u, codebook2.v);
+
+ const CinepakCodebook &codebook3 = strip.v4_codebook[codebookIndex[2]];
+ putPixelRaw(rows[2] + 0, clipTable, format, codebook3.y[0], codebook3.u, codebook3.v);
+ putPixelRaw(rows[2] + 1, clipTable, format, codebook3.y[1], codebook3.u, codebook3.v);
+ putPixelRaw(rows[3] + 0, clipTable, format, codebook3.y[2], codebook3.u, codebook3.v);
+ putPixelRaw(rows[3] + 1, clipTable, format, codebook3.y[3], codebook3.u, codebook3.v);
+
+ const CinepakCodebook &codebook4 = strip.v4_codebook[codebookIndex[3]];
+ putPixelRaw(rows[2] + 2, clipTable, format, codebook4.y[0], codebook4.u, codebook4.v);
+ putPixelRaw(rows[2] + 3, clipTable, format, codebook4.y[1], codebook4.u, codebook4.v);
+ putPixelRaw(rows[3] + 2, clipTable, format, codebook4.y[2], codebook4.u, codebook4.v);
+ putPixelRaw(rows[3] + 3, clipTable, format, codebook4.y[3], codebook4.u, codebook4.v);
+ }
+};
+
+/**
+ * Codebook converter that dithers in VFW-style
+ */
+struct CodebookConverterDitherVFW {
+ static inline void decodeBlock1(byte codebookIndex, const CinepakStrip &strip, byte *(&rows)[4], const byte *clipTable, const byte *colorMap, const Graphics::PixelFormat &format) {
+ const CinepakCodebook &codebook = strip.v1_codebook[codebookIndex];
+ byte blockBuffer[16];
+ ditherCodebookSmooth(codebook, blockBuffer, colorMap);
+ rows[0][0] = blockBuffer[0];
+ rows[0][1] = blockBuffer[1];
+ rows[0][2] = blockBuffer[2];
+ rows[0][3] = blockBuffer[3];
+ rows[1][0] = blockBuffer[4];
+ rows[1][1] = blockBuffer[5];
+ rows[1][2] = blockBuffer[6];
+ rows[1][3] = blockBuffer[7];
+ rows[2][0] = blockBuffer[8];
+ rows[2][1] = blockBuffer[9];
+ rows[2][2] = blockBuffer[10];
+ rows[2][3] = blockBuffer[11];
+ rows[3][0] = blockBuffer[12];
+ rows[3][1] = blockBuffer[13];
+ rows[3][2] = blockBuffer[14];
+ rows[3][3] = blockBuffer[15];
+ }
+
+ static inline void decodeBlock4(const byte (&codebookIndex)[4], const CinepakStrip &strip, byte *(&rows)[4], const byte *clipTable, const byte *colorMap, const Graphics::PixelFormat &format) {
+ byte blockBuffer[16];
+ ditherCodebookDetail(strip.v4_codebook[codebookIndex[0]], blockBuffer, colorMap);
+ rows[0][0] = blockBuffer[0];
+ rows[0][1] = blockBuffer[1];
+ rows[1][0] = blockBuffer[4];
+ rows[1][1] = blockBuffer[5];
+
+ ditherCodebookDetail(strip.v4_codebook[codebookIndex[1]], blockBuffer, colorMap);
+ rows[0][2] = blockBuffer[2];
+ rows[0][3] = blockBuffer[3];
+ rows[1][2] = blockBuffer[6];
+ rows[1][3] = blockBuffer[7];
+
+ ditherCodebookDetail(strip.v4_codebook[codebookIndex[2]], blockBuffer, colorMap);
+ rows[2][0] = blockBuffer[8];
+ rows[2][1] = blockBuffer[9];
+ rows[3][0] = blockBuffer[12];
+ rows[3][1] = blockBuffer[13];
+
+ ditherCodebookDetail(strip.v4_codebook[codebookIndex[3]], blockBuffer, colorMap);
+ rows[2][2] = blockBuffer[10];
+ rows[2][3] = blockBuffer[11];
+ rows[3][2] = blockBuffer[14];
+ rows[3][3] = blockBuffer[15];
+ }
+
+private:
+ static inline void ditherCodebookDetail(const CinepakCodebook &codebook, byte *dst, const byte *colorMap) {
+ int uLookup = (byte)codebook.u * 2;
+ int vLookup = (byte)codebook.v * 2;
+ uint32 uv1 = s_uLookup[uLookup] | s_vLookup[vLookup];
+ uint32 uv2 = s_uLookup[uLookup + 1] | s_vLookup[vLookup + 1];
+
+ int yLookup1 = codebook.y[0] * 2;
+ int yLookup2 = codebook.y[1] * 2;
+ int yLookup3 = codebook.y[2] * 2;
+ int yLookup4 = codebook.y[3] * 2;
+
+ uint32 pixelGroup1 = uv2 | s_yLookup[yLookup1 + 1];
+ uint32 pixelGroup2 = uv2 | s_yLookup[yLookup2 + 1];
+ uint32 pixelGroup3 = uv1 | s_yLookup[yLookup3];
+ uint32 pixelGroup4 = uv1 | s_yLookup[yLookup4];
+ uint32 pixelGroup5 = uv1 | s_yLookup[yLookup1];
+ uint32 pixelGroup6 = uv1 | s_yLookup[yLookup2];
+ uint32 pixelGroup7 = uv2 | s_yLookup[yLookup3 + 1];
+ uint32 pixelGroup8 = uv2 | s_yLookup[yLookup4 + 1];
+
+ dst[0] = getRGBLookupEntry(colorMap, pixelGroup1 & 0xFFFF);
+ dst[1] = getRGBLookupEntry(colorMap, pixelGroup2 >> 16);
+ dst[2] = getRGBLookupEntry(colorMap, pixelGroup5 & 0xFFFF);
+ dst[3] = getRGBLookupEntry(colorMap, pixelGroup6 >> 16);
+ dst[4] = getRGBLookupEntry(colorMap, pixelGroup3 & 0xFFFF);
+ dst[5] = getRGBLookupEntry(colorMap, pixelGroup4 >> 16);
+ dst[6] = getRGBLookupEntry(colorMap, pixelGroup7 & 0xFFFF);
+ dst[7] = getRGBLookupEntry(colorMap, pixelGroup8 >> 16);
+ dst[8] = getRGBLookupEntry(colorMap, pixelGroup1 >> 16);
+ dst[9] = getRGBLookupEntry(colorMap, pixelGroup6 & 0xFFFF);
+ dst[10] = getRGBLookupEntry(colorMap, pixelGroup5 >> 16);
+ dst[11] = getRGBLookupEntry(colorMap, pixelGroup2 & 0xFFFF);
+ dst[12] = getRGBLookupEntry(colorMap, pixelGroup3 >> 16);
+ dst[13] = getRGBLookupEntry(colorMap, pixelGroup8 & 0xFFFF);
+ dst[14] = getRGBLookupEntry(colorMap, pixelGroup7 >> 16);
+ dst[15] = getRGBLookupEntry(colorMap, pixelGroup4 & 0xFFFF);
+ }
+
+ static inline void ditherCodebookSmooth(const CinepakCodebook &codebook, byte *dst, const byte *colorMap) {
+ int uLookup = (byte)codebook.u * 2;
+ int vLookup = (byte)codebook.v * 2;
+ uint32 uv1 = s_uLookup[uLookup] | s_vLookup[vLookup];
+ uint32 uv2 = s_uLookup[uLookup + 1] | s_vLookup[vLookup + 1];
+
+ int yLookup1 = codebook.y[0] * 2;
+ int yLookup2 = codebook.y[1] * 2;
+ int yLookup3 = codebook.y[2] * 2;
+ int yLookup4 = codebook.y[3] * 2;
+
+ uint32 pixelGroup1 = uv2 | s_yLookup[yLookup1 + 1];
+ uint32 pixelGroup2 = uv1 | s_yLookup[yLookup2];
+ uint32 pixelGroup3 = uv1 | s_yLookup[yLookup1];
+ uint32 pixelGroup4 = uv2 | s_yLookup[yLookup2 + 1];
+ uint32 pixelGroup5 = uv2 | s_yLookup[yLookup3 + 1];
+ uint32 pixelGroup6 = uv1 | s_yLookup[yLookup3];
+ uint32 pixelGroup7 = uv1 | s_yLookup[yLookup4];
+ uint32 pixelGroup8 = uv2 | s_yLookup[yLookup4 + 1];
+
+ dst[0] = getRGBLookupEntry(colorMap, pixelGroup1 & 0xFFFF);
+ dst[1] = getRGBLookupEntry(colorMap, pixelGroup1 >> 16);
+ dst[2] = getRGBLookupEntry(colorMap, pixelGroup2 & 0xFFFF);
+ dst[3] = getRGBLookupEntry(colorMap, pixelGroup2 >> 16);
+ dst[4] = getRGBLookupEntry(colorMap, pixelGroup3 & 0xFFFF);
+ dst[5] = getRGBLookupEntry(colorMap, pixelGroup3 >> 16);
+ dst[6] = getRGBLookupEntry(colorMap, pixelGroup4 & 0xFFFF);
+ dst[7] = getRGBLookupEntry(colorMap, pixelGroup4 >> 16);
+ dst[8] = getRGBLookupEntry(colorMap, pixelGroup5 >> 16);
+ dst[9] = getRGBLookupEntry(colorMap, pixelGroup6 & 0xFFFF);
+ dst[10] = getRGBLookupEntry(colorMap, pixelGroup7 >> 16);
+ dst[11] = getRGBLookupEntry(colorMap, pixelGroup8 & 0xFFFF);
+ dst[12] = getRGBLookupEntry(colorMap, pixelGroup6 >> 16);
+ dst[13] = getRGBLookupEntry(colorMap, pixelGroup5 & 0xFFFF);
+ dst[14] = getRGBLookupEntry(colorMap, pixelGroup8 >> 16);
+ dst[15] = getRGBLookupEntry(colorMap, pixelGroup7 & 0xFFFF);
+ }
+
+ static inline byte getRGBLookupEntry(const byte *colorMap, uint16 index) {
+ return colorMap[s_defaultPaletteLookup[CLIP<int>(index, 0, 1024)]];
+ }
+};
+
+template<typename PixelInt, typename CodebookConverter>
+void decodeVectorsTmpl(CinepakFrame &frame, const byte *clipTable, const byte *colorMap, Common::SeekableReadStream &stream, uint16 strip, byte chunkID, uint32 chunkSize) {
+ uint32 flag = 0, mask = 0;
+ PixelInt *iy[4];
+ int32 startPos = stream.pos();
+
+ for (uint16 y = frame.strips[strip].rect.top; y < frame.strips[strip].rect.bottom; y += 4) {
+ iy[0] = (PixelInt *)frame.surface->getBasePtr(frame.strips[strip].rect.left, + y);
+ iy[1] = iy[0] + frame.width;
+ iy[2] = iy[1] + frame.width;
+ iy[3] = iy[2] + frame.width;
+
+ for (uint16 x = frame.strips[strip].rect.left; x < frame.strips[strip].rect.right; x += 4) {
+ if ((chunkID & 0x01) && !(mask >>= 1)) {
+ if ((stream.pos() - startPos + 4) > (int32)chunkSize)
+ return;
+
+ flag = stream.readUint32BE();
+ mask = 0x80000000;
+ }
+
+ if (!(chunkID & 0x01) || (flag & mask)) {
+ if (!(chunkID & 0x02) && !(mask >>= 1)) {
+ if ((stream.pos() - startPos + 4) > (int32)chunkSize)
+ return;
+
+ flag = stream.readUint32BE();
+ mask = 0x80000000;
+ }
+
+ if ((chunkID & 0x02) || (~flag & mask)) {
+ if ((stream.pos() - startPos + 1) > (int32)chunkSize)
+ return;
+
+ // Get the codebook
+ byte codebook = stream.readByte();
+ CodebookConverter::decodeBlock1(codebook, frame.strips[strip], iy, clipTable, colorMap, frame.surface->format);
+ } else if (flag & mask) {
+ if ((stream.pos() - startPos + 4) > (int32)chunkSize)
+ return;
+
+ byte codebook[4];
+ for (byte i = 0; i < 4; i++)
+ codebook[i] = stream.readByte();
+ CodebookConverter::decodeBlock4(codebook, frame.strips[strip], iy, clipTable, colorMap, frame.surface->format);
+ }
+ }
+
+ for (byte i = 0; i < 4; i++)
+ iy[i] += 4;
+ }
+ }
+}
+
+} // End of anonymous namespace
CinepakDecoder::CinepakDecoder(int bitsPerPixel) : Codec(), _bitsPerPixel(bitsPerPixel) {
_curFrame.surface = 0;
@@ -230,93 +502,12 @@ void CinepakDecoder::loadCodebook(Common::SeekableReadStream &stream, uint16 str
}
void CinepakDecoder::decodeVectors(Common::SeekableReadStream &stream, uint16 strip, byte chunkID, uint32 chunkSize) {
- uint32 flag = 0, mask = 0;
- uint32 iy[4];
- int32 startPos = stream.pos();
-
- for (uint16 y = _curFrame.strips[strip].rect.top; y < _curFrame.strips[strip].rect.bottom; y += 4) {
- iy[0] = _curFrame.strips[strip].rect.left + y * _curFrame.width;
- iy[1] = iy[0] + _curFrame.width;
- iy[2] = iy[1] + _curFrame.width;
- iy[3] = iy[2] + _curFrame.width;
-
- for (uint16 x = _curFrame.strips[strip].rect.left; x < _curFrame.strips[strip].rect.right; x += 4) {
- if ((chunkID & 0x01) && !(mask >>= 1)) {
- if ((stream.pos() - startPos + 4) > (int32)chunkSize)
- return;
-
- flag = stream.readUint32BE();
- mask = 0x80000000;
- }
-
- if (!(chunkID & 0x01) || (flag & mask)) {
- if (!(chunkID & 0x02) && !(mask >>= 1)) {
- if ((stream.pos() - startPos + 4) > (int32)chunkSize)
- return;
-
- flag = stream.readUint32BE();
- mask = 0x80000000;
- }
-
- if ((chunkID & 0x02) || (~flag & mask)) {
- if ((stream.pos() - startPos + 1) > (int32)chunkSize)
- return;
-
- // Get the codebook
- CinepakCodebook codebook = _curFrame.strips[strip].v1_codebook[stream.readByte()];
-
- PUT_PIXEL(iy[0] + 0, codebook.y[0], codebook.u, codebook.v);
- PUT_PIXEL(iy[0] + 1, codebook.y[0], codebook.u, codebook.v);
- PUT_PIXEL(iy[1] + 0, codebook.y[0], codebook.u, codebook.v);
- PUT_PIXEL(iy[1] + 1, codebook.y[0], codebook.u, codebook.v);
-
- PUT_PIXEL(iy[0] + 2, codebook.y[1], codebook.u, codebook.v);
- PUT_PIXEL(iy[0] + 3, codebook.y[1], codebook.u, codebook.v);
- PUT_PIXEL(iy[1] + 2, codebook.y[1], codebook.u, codebook.v);
- PUT_PIXEL(iy[1] + 3, codebook.y[1], codebook.u, codebook.v);
-
- PUT_PIXEL(iy[2] + 0, codebook.y[2], codebook.u, codebook.v);
- PUT_PIXEL(iy[2] + 1, codebook.y[2], codebook.u, codebook.v);
- PUT_PIXEL(iy[3] + 0, codebook.y[2], codebook.u, codebook.v);
- PUT_PIXEL(iy[3] + 1, codebook.y[2], codebook.u, codebook.v);
-
- PUT_PIXEL(iy[2] + 2, codebook.y[3], codebook.u, codebook.v);
- PUT_PIXEL(iy[2] + 3, codebook.y[3], codebook.u, codebook.v);
- PUT_PIXEL(iy[3] + 2, codebook.y[3], codebook.u, codebook.v);
- PUT_PIXEL(iy[3] + 3, codebook.y[3], codebook.u, codebook.v);
- } else if (flag & mask) {
- if ((stream.pos() - startPos + 4) > (int32)chunkSize)
- return;
-
- CinepakCodebook codebook = _curFrame.strips[strip].v4_codebook[stream.readByte()];
- PUT_PIXEL(iy[0] + 0, codebook.y[0], codebook.u, codebook.v);
- PUT_PIXEL(iy[0] + 1, codebook.y[1], codebook.u, codebook.v);
- PUT_PIXEL(iy[1] + 0, codebook.y[2], codebook.u, codebook.v);
- PUT_PIXEL(iy[1] + 1, codebook.y[3], codebook.u, codebook.v);
-
- codebook = _curFrame.strips[strip].v4_codebook[stream.readByte()];
- PUT_PIXEL(iy[0] + 2, codebook.y[0], codebook.u, codebook.v);
- PUT_PIXEL(iy[0] + 3, codebook.y[1], codebook.u, codebook.v);
- PUT_PIXEL(iy[1] + 2, codebook.y[2], codebook.u, codebook.v);
- PUT_PIXEL(iy[1] + 3, codebook.y[3], codebook.u, codebook.v);
-
- codebook = _curFrame.strips[strip].v4_codebook[stream.readByte()];
- PUT_PIXEL(iy[2] + 0, codebook.y[0], codebook.u, codebook.v);
- PUT_PIXEL(iy[2] + 1, codebook.y[1], codebook.u, codebook.v);
- PUT_PIXEL(iy[3] + 0, codebook.y[2], codebook.u, codebook.v);
- PUT_PIXEL(iy[3] + 1, codebook.y[3], codebook.u, codebook.v);
-
- codebook = _curFrame.strips[strip].v4_codebook[stream.readByte()];
- PUT_PIXEL(iy[2] + 2, codebook.y[0], codebook.u, codebook.v);
- PUT_PIXEL(iy[2] + 3, codebook.y[1], codebook.u, codebook.v);
- PUT_PIXEL(iy[3] + 2, codebook.y[2], codebook.u, codebook.v);
- PUT_PIXEL(iy[3] + 3, codebook.y[3], codebook.u, codebook.v);
- }
- }
-
- for (byte i = 0; i < 4; i++)
- iy[i] += 4;
- }
+ if (_curFrame.surface->format.bytesPerPixel == 1) {
+ decodeVectorsTmpl<byte, CodebookConverterRaw>(_curFrame, _clipTable, _colorMap, stream, strip, chunkID, chunkSize);
+ } else if (_curFrame.surface->format.bytesPerPixel == 2) {
+ decodeVectorsTmpl<uint16, CodebookConverterRaw>(_curFrame, _clipTable, _colorMap, stream, strip, chunkID, chunkSize);
+ } else if (_curFrame.surface->format.bytesPerPixel == 4) {
+ decodeVectorsTmpl<uint32, CodebookConverterRaw>(_curFrame, _clipTable, _colorMap, stream, strip, chunkID, chunkSize);
}
}
@@ -376,171 +567,7 @@ byte CinepakDecoder::findNearestRGB(int index) const {
}
void CinepakDecoder::ditherVectors(Common::SeekableReadStream &stream, uint16 strip, byte chunkID, uint32 chunkSize) {
- uint32 flag = 0, mask = 0;
- byte *iy[4];
- int32 startPos = stream.pos();
-
- for (uint16 y = _curFrame.strips[strip].rect.top; y < _curFrame.strips[strip].rect.bottom; y += 4) {
- iy[0] = (byte *)_curFrame.surface->getPixels() + _curFrame.strips[strip].rect.left + y * _curFrame.width;
- iy[1] = iy[0] + _curFrame.width;
- iy[2] = iy[1] + _curFrame.width;
- iy[3] = iy[2] + _curFrame.width;
-
- for (uint16 x = _curFrame.strips[strip].rect.left; x < _curFrame.strips[strip].rect.right; x += 4) {
- if ((chunkID & 0x01) && !(mask >>= 1)) {
- if ((stream.pos() - startPos + 4) > (int32)chunkSize)
- return;
-
- flag = stream.readUint32BE();
- mask = 0x80000000;
- }
-
- if (!(chunkID & 0x01) || (flag & mask)) {
- if (!(chunkID & 0x02) && !(mask >>= 1)) {
- if ((stream.pos() - startPos + 4) > (int32)chunkSize)
- return;
-
- flag = stream.readUint32BE();
- mask = 0x80000000;
- }
-
- byte blockBuffer[16];
-
- if ((chunkID & 0x02) || (~flag & mask)) {
- if ((stream.pos() - startPos + 1) > (int32)chunkSize)
- return;
-
- ditherCodebookSmooth(_curFrame.strips[strip].v1_codebook[stream.readByte()], blockBuffer);
- iy[0][0] = blockBuffer[0];
- iy[0][1] = blockBuffer[1];
- iy[0][2] = blockBuffer[2];
- iy[0][3] = blockBuffer[3];
- iy[1][0] = blockBuffer[4];
- iy[1][1] = blockBuffer[5];
- iy[1][2] = blockBuffer[6];
- iy[1][3] = blockBuffer[7];
- iy[2][0] = blockBuffer[8];
- iy[2][1] = blockBuffer[9];
- iy[2][2] = blockBuffer[10];
- iy[2][3] = blockBuffer[11];
- iy[3][0] = blockBuffer[12];
- iy[3][1] = blockBuffer[13];
- iy[3][2] = blockBuffer[14];
- iy[3][3] = blockBuffer[15];
- } else if (flag & mask) {
- if ((stream.pos() - startPos + 4) > (int32)chunkSize)
- return;
-
- ditherCodebookDetail(_curFrame.strips[strip].v4_codebook[stream.readByte()], blockBuffer);
- iy[0][0] = blockBuffer[0];
- iy[0][1] = blockBuffer[1];
- iy[1][0] = blockBuffer[4];
- iy[1][1] = blockBuffer[5];
-
- ditherCodebookDetail(_curFrame.strips[strip].v4_codebook[stream.readByte()], blockBuffer);
- iy[0][2] = blockBuffer[2];
- iy[0][3] = blockBuffer[3];
- iy[1][2] = blockBuffer[6];
- iy[1][3] = blockBuffer[7];
-
- ditherCodebookDetail(_curFrame.strips[strip].v4_codebook[stream.readByte()], blockBuffer);
- iy[2][0] = blockBuffer[8];
- iy[2][1] = blockBuffer[9];
- iy[3][0] = blockBuffer[12];
- iy[3][1] = blockBuffer[13];
-
- ditherCodebookDetail(_curFrame.strips[strip].v4_codebook[stream.readByte()], blockBuffer);
- iy[2][2] = blockBuffer[10];
- iy[2][3] = blockBuffer[11];
- iy[3][2] = blockBuffer[14];
- iy[3][3] = blockBuffer[15];
- }
- }
-
- for (byte i = 0; i < 4; i++)
- iy[i] += 4;
- }
- }
-}
-
-void CinepakDecoder::ditherCodebookDetail(const CinepakCodebook &codebook, byte *dst) const {
- int uLookup = (byte)codebook.u * 2;
- int vLookup = (byte)codebook.v * 2;
- uint32 uv1 = s_uLookup[uLookup] | s_vLookup[vLookup];
- uint32 uv2 = s_uLookup[uLookup + 1] | s_vLookup[vLookup + 1];
-
- int yLookup1 = codebook.y[0] * 2;
- int yLookup2 = codebook.y[1] * 2;
- int yLookup3 = codebook.y[2] * 2;
- int yLookup4 = codebook.y[3] * 2;
-
- uint32 pixelGroup1 = uv2 | s_yLookup[yLookup1 + 1];
- uint32 pixelGroup2 = uv2 | s_yLookup[yLookup2 + 1];
- uint32 pixelGroup3 = uv1 | s_yLookup[yLookup3];
- uint32 pixelGroup4 = uv1 | s_yLookup[yLookup4];
- uint32 pixelGroup5 = uv1 | s_yLookup[yLookup1];
- uint32 pixelGroup6 = uv1 | s_yLookup[yLookup2];
- uint32 pixelGroup7 = uv2 | s_yLookup[yLookup3 + 1];
- uint32 pixelGroup8 = uv2 | s_yLookup[yLookup4 + 1];
-
- dst[0] = getRGBLookupEntry(pixelGroup1 & 0xFFFF);
- dst[1] = getRGBLookupEntry(pixelGroup2 >> 16);
- dst[2] = getRGBLookupEntry(pixelGroup5 & 0xFFFF);
- dst[3] = getRGBLookupEntry(pixelGroup6 >> 16);
- dst[4] = getRGBLookupEntry(pixelGroup3 & 0xFFFF);
- dst[5] = getRGBLookupEntry(pixelGroup4 >> 16);
- dst[6] = getRGBLookupEntry(pixelGroup7 & 0xFFFF);
- dst[7] = getRGBLookupEntry(pixelGroup8 >> 16);
- dst[8] = getRGBLookupEntry(pixelGroup1 >> 16);
- dst[9] = getRGBLookupEntry(pixelGroup6 & 0xFFFF);
- dst[10] = getRGBLookupEntry(pixelGroup5 >> 16);
- dst[11] = getRGBLookupEntry(pixelGroup2 & 0xFFFF);
- dst[12] = getRGBLookupEntry(pixelGroup3 >> 16);
- dst[13] = getRGBLookupEntry(pixelGroup8 & 0xFFFF);
- dst[14] = getRGBLookupEntry(pixelGroup7 >> 16);
- dst[15] = getRGBLookupEntry(pixelGroup4 & 0xFFFF);
-}
-
-void CinepakDecoder::ditherCodebookSmooth(const CinepakCodebook &codebook, byte *dst) const {
- int uLookup = (byte)codebook.u * 2;
- int vLookup = (byte)codebook.v * 2;
- uint32 uv1 = s_uLookup[uLookup] | s_vLookup[vLookup];
- uint32 uv2 = s_uLookup[uLookup + 1] | s_vLookup[vLookup + 1];
-
- int yLookup1 = codebook.y[0] * 2;
- int yLookup2 = codebook.y[1] * 2;
- int yLookup3 = codebook.y[2] * 2;
- int yLookup4 = codebook.y[3] * 2;
-
- uint32 pixelGroup1 = uv2 | s_yLookup[yLookup1 + 1];
- uint32 pixelGroup2 = uv1 | s_yLookup[yLookup2];
- uint32 pixelGroup3 = uv1 | s_yLookup[yLookup1];
- uint32 pixelGroup4 = uv2 | s_yLookup[yLookup2 + 1];
- uint32 pixelGroup5 = uv2 | s_yLookup[yLookup3 + 1];
- uint32 pixelGroup6 = uv1 | s_yLookup[yLookup3];
- uint32 pixelGroup7 = uv1 | s_yLookup[yLookup4];
- uint32 pixelGroup8 = uv2 | s_yLookup[yLookup4 + 1];
-
- dst[0] = getRGBLookupEntry(pixelGroup1 & 0xFFFF);
- dst[1] = getRGBLookupEntry(pixelGroup1 >> 16);
- dst[2] = getRGBLookupEntry(pixelGroup2 & 0xFFFF);
- dst[3] = getRGBLookupEntry(pixelGroup2 >> 16);
- dst[4] = getRGBLookupEntry(pixelGroup3 & 0xFFFF);
- dst[5] = getRGBLookupEntry(pixelGroup3 >> 16);
- dst[6] = getRGBLookupEntry(pixelGroup4 & 0xFFFF);
- dst[7] = getRGBLookupEntry(pixelGroup4 >> 16);
- dst[8] = getRGBLookupEntry(pixelGroup5 >> 16);
- dst[9] = getRGBLookupEntry(pixelGroup6 & 0xFFFF);
- dst[10] = getRGBLookupEntry(pixelGroup7 >> 16);
- dst[11] = getRGBLookupEntry(pixelGroup8 & 0xFFFF);
- dst[12] = getRGBLookupEntry(pixelGroup6 >> 16);
- dst[13] = getRGBLookupEntry(pixelGroup5 & 0xFFFF);
- dst[14] = getRGBLookupEntry(pixelGroup8 >> 16);
- dst[15] = getRGBLookupEntry(pixelGroup7 & 0xFFFF);
-}
-
-byte CinepakDecoder::getRGBLookupEntry(uint16 index) const {
- return _colorMap[s_defaultPaletteLookup[CLIP<int>(index, 0, 1024)]];
+ decodeVectorsTmpl<byte, CodebookConverterDitherVFW>(_curFrame, _clipTable, _colorMap, stream, strip, chunkID, chunkSize);
}
} // End of namespace Image
diff --git a/image/codecs/cinepak.h b/image/codecs/cinepak.h
index ccdad0877c..02c09b6ddb 100644
--- a/image/codecs/cinepak.h
+++ b/image/codecs/cinepak.h
@@ -95,9 +95,6 @@ private:
byte findNearestRGB(int index) const;
void ditherVectors(Common::SeekableReadStream &stream, uint16 strip, byte chunkID, uint32 chunkSize);
- void ditherCodebookDetail(const CinepakCodebook &codebook, byte *dst) const;
- void ditherCodebookSmooth(const CinepakCodebook &codebook, byte *dst) const;
- byte getRGBLookupEntry(uint16 index) const;
};
} // End of namespace Image