aboutsummaryrefslogtreecommitdiff
path: root/image/codecs
diff options
context:
space:
mode:
authorColin Snover2017-08-24 16:41:51 -0500
committerColin Snover2017-08-24 20:36:08 -0500
commit4a39f85c1b283fe17531cfab4ba9b0cb7a6bd928 (patch)
treed2391491a9b6d8117959d7ab736076f04bf1114e /image/codecs
parentd39a9272bf0334e5e98801ba06df89b4f59b79b8 (diff)
downloadscummvm-rg350-4a39f85c1b283fe17531cfab4ba9b0cb7a6bd928.tar.gz
scummvm-rg350-4a39f85c1b283fe17531cfab4ba9b0cb7a6bd928.tar.bz2
scummvm-rg350-4a39f85c1b283fe17531cfab4ba9b0cb7a6bd928.zip
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.
Diffstat (limited to 'image/codecs')
-rw-r--r--image/codecs/indeo/indeo.cpp3
-rw-r--r--image/codecs/indeo/indeo.h1
-rw-r--r--image/codecs/indeo4.cpp36
3 files changed, 18 insertions, 22 deletions
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<int>(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