diff options
author | Matthew Hoops | 2014-08-23 09:49:35 -0400 |
---|---|---|
committer | Matthew Hoops | 2015-04-11 14:36:42 -0400 |
commit | e5048ecffed49eb0ddb6b69488cfeebbc3820d8f (patch) | |
tree | d2cb820fc9fca06e70c4a5c6cef41d3a2f9b24a4 | |
parent | f342d63431fc0784adc08648f17a6bbad934743f (diff) | |
download | scummvm-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.cpp | 555 | ||||
-rw-r--r-- | image/codecs/cinepak.h | 3 |
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 |