From 4a39f85c1b283fe17531cfab4ba9b0cb7a6bd928 Mon Sep 17 00:00:00 2001 From: Colin Snover Date: Thu, 24 Aug 2017 16:41:51 -0500 Subject: IMAGE: Implement handling of key color in Indeo transparency This should also improve performance by eliminating unnecessary writes to the output bitmap for opaque pixels and by simplifying the rendering loop. --- image/codecs/indeo/indeo.cpp | 3 ++- image/codecs/indeo/indeo.h | 1 + image/codecs/indeo4.cpp | 36 +++++++++++++++--------------------- 3 files changed, 18 insertions(+), 22 deletions(-) (limited to 'image/codecs') diff --git a/image/codecs/indeo/indeo.cpp b/image/codecs/indeo/indeo.cpp index 27db365cf0..34377537d7 100644 --- a/image/codecs/indeo/indeo.cpp +++ b/image/codecs/indeo/indeo.cpp @@ -444,7 +444,8 @@ IVI45DecContext::IVI45DecContext() : _gb(nullptr), _frameNum(0), _frameType(0), _bRefBuf(0), _rvmapSel(0), _inImf(false), _inQ(false), _picGlobQuant(0), _unknown1(0), _gopHdrSize(0), _gopFlags(0), _lockWord(0), _hasBFrames(false), _hasTransp(false), _usesTiling(false), _usesHaar(false), _usesFullpel(false), - _gopInvalid(false), _isIndeo4(false), _pFrame(nullptr), _gotPFrame(false) { + _gopInvalid(false), _isIndeo4(false), _transKeyColor(0), _pFrame(nullptr), + _gotPFrame(false) { Common::fill(&_bufInvalid[0], &_bufInvalid[4], 0); Common::copy(&_ff_ivi_rvmap_tabs[0], &_ff_ivi_rvmap_tabs[9], &_rvmapTabs[0]); diff --git a/image/codecs/indeo/indeo.h b/image/codecs/indeo/indeo.h index 6c2a6b17a2..d9740ecf61 100644 --- a/image/codecs/indeo/indeo.h +++ b/image/codecs/indeo/indeo.h @@ -420,6 +420,7 @@ public: int _bufInvalid[4]; bool _isIndeo4; + uint32 _transKeyColor; AVFrame * _pFrame; bool _gotPFrame; diff --git a/image/codecs/indeo4.cpp b/image/codecs/indeo4.cpp index 65aed6a559..bc777cfb85 100644 --- a/image/codecs/indeo4.cpp +++ b/image/codecs/indeo4.cpp @@ -26,6 +26,7 @@ * written, produced, and directed by Alan Smithee */ +#include "common/algorithm.h" #include "common/debug.h" #include "common/memstream.h" #include "common/rect.h" @@ -111,6 +112,12 @@ int Indeo4Decoder::decodePictureHeader() { _ctx._hasBFrames = true; _ctx._hasTransp = _ctx._gb->getBit(); + if (_ctx._hasTransp && _surface.format.aBits() == 0) { + // Surface is 4 bytes per pixel, but only RGB. So promote the + // surface to full RGBA, and convert all the existing pixels + _pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0); + _surface.convertToInPlace(_pixelFormat); + } // unknown bit: Mac decoder ignores this bit, XANIM returns error if (_ctx._gb->getBit()) { @@ -605,8 +612,6 @@ int Indeo4Decoder::decodeRLETransparency(VLC_TYPE (*table)[2]) { bool runIsOpaque = _ctx._gb->getBit(); bool nextRunIsOpaque = !runIsOpaque; - const uint32 opacityMask = 0xFF << _pixelFormat.aShift; - uint32 *pixel = (uint32 *)_surface.getPixels(); const int surfacePixelPitch = _surface.pitch / _surface.format.bytesPerPixel; const int surfacePadding = surfacePixelPitch - _surface.w; @@ -655,14 +660,12 @@ int Indeo4Decoder::decodeRLETransparency(VLC_TYPE (*table)[2]) { } while (value > 0) { - if (runIsOpaque) { - *pixel = *pixel | opacityMask; - } else { - *pixel = *pixel & ~opacityMask; + const int length = MIN(value, endOfVisibleRow - pixel); + if (!runIsOpaque) { + Common::fill(pixel, pixel + length, _ctx._transKeyColor); } - - --value; - ++pixel; + value -= length; + pixel += length; if (pixel == endOfVisibleRow) { pixel += surfacePadding; @@ -715,11 +718,9 @@ int Indeo4Decoder::decodeTransparency() { if (_ctx._gb->getBit()) { /* @350 */ /* @358 */ - int unknown = (_ctx._gb->getBits(8) << 16) | (_ctx._gb->getBits(8) << 8) | (_ctx._gb->getBits(8)); - debug(4, "Indeo4: Unknown is %08x", unknown); + _ctx._transKeyColor = _surface.format.ARGBToColor(0, _ctx._gb->getBits(8), _ctx._gb->getBits(8), _ctx._gb->getBits(8)); + debug(4, "Indeo4: Key color is %08x", _ctx._transKeyColor); /* @477 */ - // This unknown value gets written out to IVIPicture.field_f8 and does - // not seem to have any obvious effect on the transparency rendering } if (_ctx._gb->getBit() == 0) { /* @4D9 */ @@ -767,13 +768,6 @@ int Indeo4Decoder::decodeTransparency() { assert(!_ctx._isScalable); assert(!_ctx._usesTiling); - if (_surface->format.aBits() == 0) { - // Surface is 4 bytes per pixel, but only RGB. So promote the - // surface to full RGBA, and convert all the existing pixels - _pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0); - _surface->convertToInPlace(_pixelFormat); - } - assert(_surface.format.bytesPerPixel == 4); assert((_surface.pitch % 4) == 0); @@ -788,7 +782,7 @@ int Indeo4Decoder::decodeTransparency() { // It should only be necessary to draw transparency here since the // data from the YUV planes gets drawn to the output surface on each // frame, which resets the surface pixels to be fully opaque - _surface.fillRect(Common::Rect(_surface.w, _surface.h), 0); + _surface.fillRect(Common::Rect(_surface.w, _surface.h), _ctx._transKeyColor); } // No alignment here -- cgit v1.2.3