diff options
author | Strangerke | 2013-09-08 14:49:34 +0200 |
---|---|---|
committer | Strangerke | 2013-09-08 14:49:34 +0200 |
commit | 599d2eeb06c937a4479cc751f4f9f5e94795c43b (patch) | |
tree | 6efd0f887d7a1fd5082209a585d609983031c92d /graphics | |
parent | 7df4c94aeb6c1408d26d6ada58d728b6eac17717 (diff) | |
parent | 03bf56ea82c0b89f4e61e5e0787a36473f999efa (diff) | |
download | scummvm-rg350-599d2eeb06c937a4479cc751f4f9f5e94795c43b.tar.gz scummvm-rg350-599d2eeb06c937a4479cc751f4f9f5e94795c43b.tar.bz2 scummvm-rg350-599d2eeb06c937a4479cc751f4f9f5e94795c43b.zip |
Merge branch 'master' into avalanche
Diffstat (limited to 'graphics')
-rw-r--r-- | graphics/VectorRenderer.h | 2 | ||||
-rw-r--r-- | graphics/VectorRendererSpec.cpp | 97 | ||||
-rw-r--r-- | graphics/cursorman.cpp | 7 | ||||
-rw-r--r-- | graphics/cursorman.h | 6 | ||||
-rw-r--r-- | graphics/decoders/bmp.cpp | 6 | ||||
-rw-r--r-- | graphics/decoders/iff.cpp | 4 | ||||
-rw-r--r-- | graphics/decoders/jpeg.cpp | 2 | ||||
-rw-r--r-- | graphics/decoders/pcx.cpp | 6 | ||||
-rw-r--r-- | graphics/decoders/pict.cpp | 2 | ||||
-rw-r--r-- | graphics/decoders/png.cpp | 2 | ||||
-rw-r--r-- | graphics/decoders/tga.cpp | 4 | ||||
-rw-r--r-- | graphics/fonts/bdf.cpp | 4 | ||||
-rw-r--r-- | graphics/fonts/ttf.cpp | 4 | ||||
-rw-r--r-- | graphics/scaler/thumbnail_intern.cpp | 217 | ||||
-rw-r--r-- | graphics/surface.cpp | 48 | ||||
-rw-r--r-- | graphics/surface.h | 77 | ||||
-rw-r--r-- | graphics/thumbnail.cpp | 118 | ||||
-rw-r--r-- | graphics/thumbnail.h | 18 | ||||
-rw-r--r-- | graphics/yuv_to_rgb.cpp | 18 | ||||
-rw-r--r-- | graphics/yuv_to_rgb.h | 15 |
20 files changed, 500 insertions, 157 deletions
diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 0467cac946..5d6369c08f 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -278,7 +278,7 @@ public: * Clears the active surface. */ virtual void clearSurface() { - byte *src = (byte *)_activeSurface->pixels; + byte *src = (byte *)_activeSurface->getPixels(); memset(src, 0, _activeSurface->pitch * _activeSurface->h); } diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index 6a3ee306a5..e4843ba78b 100644 --- a/graphics/VectorRendererSpec.cpp +++ b/graphics/VectorRendererSpec.cpp @@ -277,16 +277,22 @@ void colorFill(PixelType *first, PixelType *last, PixelType color) { VectorRenderer *createRenderer(int mode) { #ifdef DISABLE_FANCY_THEMES - assert(mode == GUI::ThemeEngine::kGfxStandard16bit); + assert(mode == GUI::ThemeEngine::kGfxStandard); #endif PixelFormat format = g_system->getOverlayFormat(); switch (mode) { - case GUI::ThemeEngine::kGfxStandard16bit: - return new VectorRendererSpec<OverlayColor>(format); + case GUI::ThemeEngine::kGfxStandard: + if (g_system->getOverlayFormat().bytesPerPixel == 4) + return new VectorRendererSpec<uint32>(format); + else if (g_system->getOverlayFormat().bytesPerPixel == 2) + return new VectorRendererSpec<uint16>(format); #ifndef DISABLE_FANCY_THEMES - case GUI::ThemeEngine::kGfxAntialias16bit: - return new VectorRendererAA<OverlayColor>(format); + case GUI::ThemeEngine::kGfxAntialias: + if (g_system->getOverlayFormat().bytesPerPixel == 4) + return new VectorRendererAA<uint32>(format); + else if (g_system->getOverlayFormat().bytesPerPixel == 2) + return new VectorRendererAA<uint16>(format); #endif default: break; @@ -317,9 +323,15 @@ setGradientColors(uint8 r1, uint8 g1, uint8 b1, uint8 r2, uint8 g2, uint8 b2) { _gradientEnd = _format.RGBToColor(r2, g2, b2); _gradientStart = _format.RGBToColor(r1, g1, b1); - _gradientBytes[0] = (_gradientEnd & _redMask) - (_gradientStart & _redMask); - _gradientBytes[1] = (_gradientEnd & _greenMask) - (_gradientStart & _greenMask); - _gradientBytes[2] = (_gradientEnd & _blueMask) - (_gradientStart & _blueMask); + if (sizeof(PixelType) == 4) { + _gradientBytes[0] = ((_gradientEnd & _redMask) >> _format.rShift) - ((_gradientStart & _redMask) >> _format.rShift); + _gradientBytes[1] = ((_gradientEnd & _greenMask) >> _format.gShift) - ((_gradientStart & _greenMask) >> _format.gShift); + _gradientBytes[2] = ((_gradientEnd & _blueMask) >> _format.bShift) - ((_gradientStart & _blueMask) >> _format.bShift); + } else { + _gradientBytes[0] = (_gradientEnd & _redMask) - (_gradientStart & _redMask); + _gradientBytes[1] = (_gradientEnd & _greenMask) - (_gradientStart & _greenMask); + _gradientBytes[2] = (_gradientEnd & _blueMask) - (_gradientStart & _blueMask); + } } template<typename PixelType> @@ -328,9 +340,15 @@ calcGradient(uint32 pos, uint32 max) { PixelType output = 0; pos = (MIN(pos * Base::_gradientFactor, max) << 12) / max; - output |= ((_gradientStart & _redMask) + ((_gradientBytes[0] * pos) >> 12)) & _redMask; - output |= ((_gradientStart & _greenMask) + ((_gradientBytes[1] * pos) >> 12)) & _greenMask; - output |= ((_gradientStart & _blueMask) + ((_gradientBytes[2] * pos) >> 12)) & _blueMask; + if (sizeof(PixelType) == 4) { + output |= ((_gradientStart & _redMask) + (((_gradientBytes[0] * pos) >> 12) << _format.rShift)) & _redMask; + output |= ((_gradientStart & _greenMask) + (((_gradientBytes[1] * pos) >> 12) << _format.gShift)) & _greenMask; + output |= ((_gradientStart & _blueMask) + (((_gradientBytes[2] * pos) >> 12) << _format.bShift)) & _blueMask; + } else { + output |= ((_gradientStart & _redMask) + ((_gradientBytes[0] * pos) >> 12)) & _redMask; + output |= ((_gradientStart & _greenMask) + ((_gradientBytes[1] * pos) >> 12)) & _greenMask; + output |= ((_gradientStart & _blueMask) + ((_gradientBytes[2] * pos) >> 12)) & _blueMask; + } output |= _alphaMask; return output; @@ -397,7 +415,7 @@ gradientFill(PixelType *ptr, int width, int x, int y) { template<typename PixelType> void VectorRendererSpec<PixelType>:: fillSurface() { - byte *ptr = (byte *)_activeSurface->getBasePtr(0, 0); + byte *ptr = (byte *)_activeSurface->getPixels(); int h = _activeSurface->h; int pitch = _activeSurface->pitch; @@ -453,7 +471,7 @@ template<typename PixelType> void VectorRendererSpec<PixelType>:: blitSubSurface(const Graphics::Surface *source, const Common::Rect &r) { byte *dst_ptr = (byte *)_activeSurface->getBasePtr(r.left, r.top); - const byte *src_ptr = (const byte *)source->getBasePtr(0, 0); + const byte *src_ptr = (const byte *)source->getPixels(); const int dst_pitch = _activeSurface->pitch; const int src_pitch = source->pitch; @@ -481,7 +499,7 @@ blitAlphaBitmap(const Graphics::Surface *source, const Common::Rect &r) { y = y + (r.height() >> 1) - (source->h >> 1); PixelType *dst_ptr = (PixelType *)_activeSurface->getBasePtr(x, y); - const PixelType *src_ptr = (const PixelType *)source->getBasePtr(0, 0); + const PixelType *src_ptr = (const PixelType *)source->getPixels(); int dst_pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel; int src_pitch = source->pitch / source->format.bytesPerPixel; @@ -508,7 +526,7 @@ template<typename PixelType> void VectorRendererSpec<PixelType>:: applyScreenShading(GUI::ThemeEngine::ShadingStyle shadingStyle) { int pixels = _activeSurface->w * _activeSurface->h; - PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(0, 0); + PixelType *ptr = (PixelType *)_activeSurface->getPixels(); uint8 r, g, b; uint lum; @@ -537,20 +555,41 @@ applyScreenShading(GUI::ThemeEngine::ShadingStyle shadingStyle) { template<typename PixelType> inline void VectorRendererSpec<PixelType>:: blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) { - int idst = *ptr; - int isrc = color; - - *ptr = (PixelType)( - (_redMask & ((idst & _redMask) + - ((int)(((int)(isrc & _redMask) - - (int)(idst & _redMask)) * alpha) >> 8))) | - (_greenMask & ((idst & _greenMask) + - ((int)(((int)(isrc & _greenMask) - - (int)(idst & _greenMask)) * alpha) >> 8))) | - (_blueMask & ((idst & _blueMask) + - ((int)(((int)(isrc & _blueMask) - - (int)(idst & _blueMask)) * alpha) >> 8))) | - (idst & _alphaMask)); + if (sizeof(PixelType) == 4) { + const byte sR = (color & _redMask) >> _format.rShift; + const byte sG = (color & _greenMask) >> _format.gShift; + const byte sB = (color & _blueMask) >> _format.bShift; + + byte dR = (*ptr & _redMask) >> _format.rShift; + byte dG = (*ptr & _greenMask) >> _format.gShift; + byte dB = (*ptr & _blueMask) >> _format.bShift; + + dR += ((sR - dR) * alpha) >> 8; + dG += ((sG - dG) * alpha) >> 8; + dB += ((sB - dB) * alpha) >> 8; + + *ptr = ((dR << _format.rShift) & _redMask) + | ((dG << _format.gShift) & _greenMask) + | ((dB << _format.bShift) & _blueMask) + | (*ptr & _alphaMask); + } else if (sizeof(PixelType) == 2) { + int idst = *ptr; + int isrc = color; + + *ptr = (PixelType)( + (_redMask & ((idst & _redMask) + + ((int)(((int)(isrc & _redMask) - + (int)(idst & _redMask)) * alpha) >> 8))) | + (_greenMask & ((idst & _greenMask) + + ((int)(((int)(isrc & _greenMask) - + (int)(idst & _greenMask)) * alpha) >> 8))) | + (_blueMask & ((idst & _blueMask) + + ((int)(((int)(isrc & _blueMask) - + (int)(idst & _blueMask)) * alpha) >> 8))) | + (idst & _alphaMask)); + } else { + error("Unsupported BPP format: %u", (uint)sizeof(PixelType)); + } } template<typename PixelType> diff --git a/graphics/cursorman.cpp b/graphics/cursorman.cpp index c818101645..6825767dfd 100644 --- a/graphics/cursorman.cpp +++ b/graphics/cursorman.cpp @@ -48,6 +48,9 @@ bool CursorManager::isVisible() { bool CursorManager::showMouse(bool visible) { if (_cursorStack.empty()) return false; + if (_locked) { + return false; + } _cursorStack.top()->_visible = visible; @@ -225,6 +228,10 @@ void CursorManager::replaceCursorPalette(const byte *colors, uint start, uint nu } } +void CursorManager::lock(bool locked) { + _locked = locked; +} + CursorManager::Cursor::Cursor(const void *data, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format) { #ifdef USE_RGB_COLOR if (!format) diff --git a/graphics/cursorman.h b/graphics/cursorman.h index 66e8d1ba56..b4d8ad94ce 100644 --- a/graphics/cursorman.h +++ b/graphics/cursorman.h @@ -160,12 +160,15 @@ public: */ void replaceCursorPalette(const byte *colors, uint start, uint num); + void lock(bool locked); private: friend class Common::Singleton<SingletonBaseType>; // Even though this is basically the default constructor we implement it // ourselves, so it is private and thus there is no way to create this class // except from the Singleton code. - CursorManager() {} + CursorManager() { + _locked = false; + } ~CursorManager(); struct Cursor { @@ -198,6 +201,7 @@ private: }; Common::Stack<Cursor *> _cursorStack; Common::Stack<Palette *> _cursorPaletteStack; + bool _locked; }; } // End of namespace Graphics diff --git a/graphics/decoders/bmp.cpp b/graphics/decoders/bmp.cpp index bcfd0abbda..2eabbb7631 100644 --- a/graphics/decoders/bmp.cpp +++ b/graphics/decoders/bmp.cpp @@ -130,14 +130,14 @@ bool BitmapDecoder::loadStream(Common::SeekableReadStream &stream) { const int extraDataLength = (srcPitch % 4) ? 4 - (srcPitch % 4) : 0; if (bitsPerPixel == 8) { - byte *dst = (byte *)_surface->pixels; + byte *dst = (byte *)_surface->getPixels(); for (int32 i = 0; i < height; i++) { stream.read(dst + (height - i - 1) * width, width); stream.skip(extraDataLength); } } else if (bitsPerPixel == 24) { - byte *dst = (byte *)_surface->pixels + (height - 1) * _surface->pitch; + byte *dst = (byte *)_surface->getBasePtr(0, height - 1); for (int32 i = 0; i < height; i++) { for (uint32 j = 0; j < width; j++) { @@ -154,7 +154,7 @@ bool BitmapDecoder::loadStream(Common::SeekableReadStream &stream) { dst -= _surface->pitch * 2; } } else { // 32 bpp - byte *dst = (byte *)_surface->pixels + (height - 1) * _surface->pitch; + byte *dst = (byte *)_surface->getBasePtr(0, height - 1); for (int32 i = 0; i < height; i++) { for (uint32 j = 0; j < width; j++) { diff --git a/graphics/decoders/iff.cpp b/graphics/decoders/iff.cpp index 50c7b4f7de..7b37969fc1 100644 --- a/graphics/decoders/iff.cpp +++ b/graphics/decoders/iff.cpp @@ -170,7 +170,7 @@ void IFFDecoder::loadBitmap(Common::SeekableReadStream &stream) { if (_type == TYPE_ILBM) { uint32 scanlinePitch = ((_header.width + 15) >> 4) << 1; byte *scanlines = new byte[scanlinePitch * _header.numPlanes]; - byte *data = (byte *)_surface->pixels; + byte *data = (byte *)_surface->getPixels(); for (uint16 i = 0; i < _header.height; ++i) { byte *scanline = scanlines; @@ -194,7 +194,7 @@ void IFFDecoder::loadBitmap(Common::SeekableReadStream &stream) { delete[] scanlines; } else if (_type == TYPE_PBM) { - byte *data = (byte *)_surface->pixels; + byte *data = (byte *)_surface->getPixels(); uint32 outSize = _header.width * _header.height; if (_header.compression) { diff --git a/graphics/decoders/jpeg.cpp b/graphics/decoders/jpeg.cpp index 75fdcd6e5a..ff018c799a 100644 --- a/graphics/decoders/jpeg.cpp +++ b/graphics/decoders/jpeg.cpp @@ -81,7 +81,7 @@ const Surface *JPEGDecoder::getSurface() const { const Graphics::Surface *uComponent = getComponent(2); const Graphics::Surface *vComponent = getComponent(3); - YUVToRGBMan.convert444(_rgbSurface, Graphics::YUVToRGBManager::kScaleFull, (byte *)yComponent->pixels, (byte *)uComponent->pixels, (byte *)vComponent->pixels, yComponent->w, yComponent->h, yComponent->pitch, uComponent->pitch); + YUVToRGBMan.convert444(_rgbSurface, Graphics::YUVToRGBManager::kScaleFull, (const byte *)yComponent->getPixels(), (const byte *)uComponent->getPixels(), (const byte *)vComponent->getPixels(), yComponent->w, yComponent->h, yComponent->pitch, uComponent->pitch); return _rgbSurface; } diff --git a/graphics/decoders/pcx.cpp b/graphics/decoders/pcx.cpp index 1250398c73..eb9b4c997d 100644 --- a/graphics/decoders/pcx.cpp +++ b/graphics/decoders/pcx.cpp @@ -117,7 +117,7 @@ bool PCXDecoder::loadStream(Common::SeekableReadStream &stream) { if (nPlanes == 3 && bitsPerPixel == 8) { // 24bpp Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0); _surface->create(width, height, format); - dst = (byte *)_surface->pixels; + dst = (byte *)_surface->getPixels(); _paletteColorCount = 0; for (y = 0; y < height; y++) { @@ -135,7 +135,7 @@ bool PCXDecoder::loadStream(Common::SeekableReadStream &stream) { } } else if (nPlanes == 1 && bitsPerPixel == 8) { // 8bpp indexed _surface->create(width, height, Graphics::PixelFormat::createFormatCLUT8()); - dst = (byte *)_surface->pixels; + dst = (byte *)_surface->getPixels(); _paletteColorCount = 16; for (y = 0; y < height; y++, dst += _surface->pitch) { @@ -163,7 +163,7 @@ bool PCXDecoder::loadStream(Common::SeekableReadStream &stream) { } } else if ((nPlanes == 2 || nPlanes == 3 || nPlanes == 4) && bitsPerPixel == 1) { // planar, 4, 8 or 16 colors _surface->create(width, height, Graphics::PixelFormat::createFormatCLUT8()); - dst = (byte *)_surface->pixels; + dst = (byte *)_surface->getPixels(); _paletteColorCount = 16; for (y = 0; y < height; y++, dst += _surface->pitch) { diff --git a/graphics/decoders/pict.cpp b/graphics/decoders/pict.cpp index b1d408ebc3..f3e17b33e2 100644 --- a/graphics/decoders/pict.cpp +++ b/graphics/decoders/pict.cpp @@ -364,7 +364,7 @@ void PICTDecoder::unpackBitsRect(Common::SeekableReadStream &stream, bool withPa case 1: // Just copy to the image _outputSurface->create(width, height, PixelFormat::createFormatCLUT8()); - memcpy(_outputSurface->pixels, buffer, _outputSurface->w * _outputSurface->h); + memcpy(_outputSurface->getPixels(), buffer, _outputSurface->w * _outputSurface->h); break; case 2: // We have a 16-bit surface diff --git a/graphics/decoders/png.cpp b/graphics/decoders/png.cpp index 11e26162eb..505475213f 100644 --- a/graphics/decoders/png.cpp +++ b/graphics/decoders/png.cpp @@ -164,7 +164,7 @@ bool PNGDecoder::loadStream(Common::SeekableReadStream &stream) { png_set_packing(pngPtr); } else { _outputSurface->create(width, height, Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)); - if (!_outputSurface->pixels) { + if (!_outputSurface->getPixels()) { error("Could not allocate memory for output image."); } if (bitDepth == 16) diff --git a/graphics/decoders/tga.cpp b/graphics/decoders/tga.cpp index c3b9d84055..a9f136d238 100644 --- a/graphics/decoders/tga.cpp +++ b/graphics/decoders/tga.cpp @@ -272,7 +272,7 @@ bool TGADecoder::readData(Common::SeekableReadStream &tga, byte imageType, byte } else if (imageType == TYPE_BW) { _surface.create(_surface.w, _surface.h, _format); - byte *data = (byte *)_surface.pixels; + byte *data = (byte *)_surface.getPixels(); uint32 count = _surface.w * _surface.h; while (count-- > 0) { @@ -318,7 +318,7 @@ bool TGADecoder::readDataRLE(Common::SeekableReadStream &tga, byte imageType, by if (imageType == TYPE_RLE_TRUECOLOR || imageType == TYPE_RLE_BW || imageType == TYPE_RLE_CMAP) { _surface.create(_surface.w, _surface.h, _format); uint32 count = _surface.w * _surface.h; - byte *data = (byte *)_surface.pixels; + byte *data = (byte *)_surface.getPixels(); while (count > 0) { uint32 header = tga.readByte(); diff --git a/graphics/fonts/bdf.cpp b/graphics/fonts/bdf.cpp index 6d4befa37c..e523a36ad5 100644 --- a/graphics/fonts/bdf.cpp +++ b/graphics/fonts/bdf.cpp @@ -102,7 +102,7 @@ void BdfFont::drawChar(Surface *dst, byte chr, const int tx, const int ty, const // equal to 50 and the decision of the theme designer? // asserting _data.maxAdvance <= 50: let the theme designer decide what looks best assert(_data.maxAdvance <= 50); - assert(dst->format.bytesPerPixel == 1 || dst->format.bytesPerPixel == 2); + assert(dst->format.bytesPerPixel == 1 || dst->format.bytesPerPixel == 2 || dst->format.bytesPerPixel == 4); const int idx = mapToIndex(chr); if (idx < 0) @@ -165,6 +165,8 @@ void BdfFont::drawChar(Surface *dst, byte chr, const int tx, const int ty, const drawCharIntern<byte>(ptr, dst->pitch, src, height, originalWidth, xStart, xEnd, color); else if (dst->format.bytesPerPixel == 2) drawCharIntern<uint16>(ptr, dst->pitch, src, height, originalWidth, xStart, xEnd, color); + else if (dst->format.bytesPerPixel == 4) + drawCharIntern<uint32>(ptr, dst->pitch, src, height, originalWidth, xStart, xEnd, color); } namespace { diff --git a/graphics/fonts/ttf.cpp b/graphics/fonts/ttf.cpp index 2b1dca1eae..b9e9610d77 100644 --- a/graphics/fonts/ttf.cpp +++ b/graphics/fonts/ttf.cpp @@ -322,7 +322,7 @@ void TTFFont::drawChar(Surface *dst, byte chr, int x, int y, uint32 color) const int w = glyph.image.w; int h = glyph.image.h; - const uint8 *srcPos = (const uint8 *)glyph.image.getBasePtr(0, 0); + const uint8 *srcPos = (const uint8 *)glyph.image.getPixels(); // Make sure we are not drawing outside the screen bounds if (x < 0) { @@ -422,7 +422,7 @@ bool TTFFont::cacheGlyph(Glyph &glyph, FT_UInt &slot, uint chr) { srcPitch = -srcPitch; } - uint8 *dst = (uint8 *)glyph.image.getBasePtr(0, 0); + uint8 *dst = (uint8 *)glyph.image.getPixels(); memset(dst, 0, glyph.image.h * glyph.image.pitch); switch (bitmap.pixel_mode) { diff --git a/graphics/scaler/thumbnail_intern.cpp b/graphics/scaler/thumbnail_intern.cpp index 88f3cc2077..c30fc3b6fd 100644 --- a/graphics/scaler/thumbnail_intern.cpp +++ b/graphics/scaler/thumbnail_intern.cpp @@ -42,8 +42,10 @@ uint16 quadBlockInterpolate(const uint8 *src, uint32 srcPitch) { template<int bitFormat> void createThumbnail_2(const uint8 *src, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) { - assert(width % 2 == 0); - assert(height % 2 == 0); + // Make sure the width and height is a multiple of 2. + width &= ~1; + height &= ~1; + for (int y = 0; y < height; y += 2) { for (int x = 0; x < width; x += 2, dstPtr += 2) { *((uint16 *)dstPtr) = quadBlockInterpolate<bitFormat>(src + 2 * x, srcPitch); @@ -55,8 +57,10 @@ void createThumbnail_2(const uint8 *src, uint32 srcPitch, uint8 *dstPtr, uint32 template<int bitFormat> void createThumbnail_4(const uint8 *src, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) { - assert(width % 4 == 0); - assert(height % 4 == 0); + // Make sure the width and height is a multiple of 4 + width &= ~3; + height &= ~3; + for (int y = 0; y < height; y += 4) { for (int x = 0; x < width; x += 4, dstPtr += 2) { uint16 upleft = quadBlockInterpolate<bitFormat>(src + 2 * x, srcPitch); @@ -71,17 +75,87 @@ void createThumbnail_4(const uint8 *src, uint32 srcPitch, uint8 *dstPtr, uint32 } } -static void createThumbnail(const uint8 *src, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) { - // only 1/2 and 1/4 downscale supported - if (width != 320 && width != 640) - return; +static void scaleThumbnail(Graphics::Surface &in, Graphics::Surface &out) { + while (in.w / out.w >= 4 || in.h / out.h >= 4) { + createThumbnail_4<565>((const uint8 *)in.getPixels(), in.pitch, (uint8 *)in.getPixels(), in.pitch, in.w, in.h); + in.w /= 4; + in.h /= 4; + } + + while (in.w / out.w >= 2 || in.h / out.h >= 2) { + createThumbnail_2<565>((const uint8 *)in.getPixels(), in.pitch, (uint8 *)in.getPixels(), in.pitch, in.w, in.h); + in.w /= 2; + in.h /= 2; + } + + if ((in.w == out.w && in.h < out.h) || (in.w < out.w && in.h == out.h)) { + // In this case we simply center the input surface in the output + uint8 *dst = (uint8 *)out.getBasePtr((out.w - in.w) / 2, (out.h - in.h) / 2); + const uint8 *src = (const uint8 *)in.getPixels(); - int downScaleMode = (width == 320) ? 2 : 4; + for (int y = 0; y < in.h; ++y) { + memcpy(dst, src, in.w * in.format.bytesPerPixel); + src += in.pitch; + dst += out.pitch; + } + } else { + // Assure the aspect of the scaled image still matches the original. + int targetWidth = out.w, targetHeight = out.h; - if (downScaleMode == 2) { - createThumbnail_2<565>(src, srcPitch, dstPtr, dstPitch, width, height); - } else if (downScaleMode == 4) { - createThumbnail_4<565>(src, srcPitch, dstPtr, dstPitch, width, height); + const float inputAspect = (float)in.w / in.h; + const float outputAspect = (float)out.w / out.h; + + if (inputAspect > outputAspect) { + targetHeight = int(targetWidth / inputAspect); + } else if (inputAspect < outputAspect) { + targetWidth = int(targetHeight * inputAspect); + } + + // Make sure we are still in the bounds of the output + assert(targetWidth <= out.w); + assert(targetHeight <= out.h); + + // Center the image on the output surface + byte *dst = (byte *)out.getBasePtr((out.w - targetWidth) / 2, (out.h - targetHeight) / 2); + const uint dstLineIncrease = out.pitch - targetWidth * out.format.bytesPerPixel; + + const float scaleFactorX = (float)targetWidth / in.w; + const float scaleFactorY = (float)targetHeight / in.h; + + for (int y = 0; y < targetHeight; ++y) { + const float yFrac = (y / scaleFactorY); + const int y1 = (int)yFrac; + const int y2 = (y1 + 1 < in.h) ? (y1 + 1) : (in.h - 1); + + for (int x = 0; x < targetWidth; ++x) { + const float xFrac = (x / scaleFactorX); + const int x1 = (int)xFrac; + const int x2 = (x1 + 1 < in.w) ? (x1 + 1) : (in.w - 1); + + // Look up colors at the points + uint8 p1R, p1G, p1B; + Graphics::colorToRGB<Graphics::ColorMasks<565> >(READ_UINT16(in.getBasePtr(x1, y1)), p1R, p1G, p1B); + uint8 p2R, p2G, p2B; + Graphics::colorToRGB<Graphics::ColorMasks<565> >(READ_UINT16(in.getBasePtr(x2, y1)), p2R, p2G, p2B); + uint8 p3R, p3G, p3B; + Graphics::colorToRGB<Graphics::ColorMasks<565> >(READ_UINT16(in.getBasePtr(x1, y2)), p3R, p3G, p3B); + uint8 p4R, p4G, p4B; + Graphics::colorToRGB<Graphics::ColorMasks<565> >(READ_UINT16(in.getBasePtr(x2, y2)), p4R, p4G, p4B); + + const float xDiff = xFrac - x1; + const float yDiff = yFrac - y1; + + uint8 pR = (uint8)((1 - yDiff) * ((1 - xDiff) * p1R + xDiff * p2R) + yDiff * ((1 - xDiff) * p3R + xDiff * p4R)); + uint8 pG = (uint8)((1 - yDiff) * ((1 - xDiff) * p1G + xDiff * p2G) + yDiff * ((1 - xDiff) * p3G + xDiff * p4G)); + uint8 pB = (uint8)((1 - yDiff) * ((1 - xDiff) * p1B + xDiff * p2B) + yDiff * ((1 - xDiff) * p3B + xDiff * p4B)); + + WRITE_UINT16(dst, Graphics::RGBToColor<Graphics::ColorMasks<565> >(pR, pG, pB)); + dst += 2; + } + + // Move to the next line + dst = (byte *)dst + dstLineIncrease; + } } } @@ -90,7 +164,7 @@ static void createThumbnail(const uint8 *src, uint32 srcPitch, uint8 *dstPtr, ui * Copies the current screen contents to a new surface, using RGB565 format. * WARNING: surf->free() must be called by the user to avoid leaking. * - * @param surf the surface to store the data in it + * @param surf the surface to store the data in it */ static bool grabScreen565(Graphics::Surface *surf) { Graphics::Surface *screen = g_system->lockScreen(); @@ -98,7 +172,7 @@ static bool grabScreen565(Graphics::Surface *surf) { return false; assert(screen->format.bytesPerPixel == 1 || screen->format.bytesPerPixel == 2); - assert(screen->pixels != 0); + assert(screen->getPixels() != 0); Graphics::PixelFormat screenFormat = g_system->getScreenFormat(); @@ -116,15 +190,16 @@ static bool grabScreen565(Graphics::Surface *surf) { byte r = 0, g = 0, b = 0; if (screenFormat.bytesPerPixel == 1) { - r = palette[((uint8 *)screen->pixels)[y * screen->pitch + x] * 3]; - g = palette[((uint8 *)screen->pixels)[y * screen->pitch + x] * 3 + 1]; - b = palette[((uint8 *)screen->pixels)[y * screen->pitch + x] * 3 + 2]; + uint8 pixel = *(uint8 *)screen->getBasePtr(x, y); + r = palette[pixel * 3 + 0]; + g = palette[pixel * 3 + 1]; + b = palette[pixel * 3 + 2]; } else if (screenFormat.bytesPerPixel == 2) { uint16 col = READ_UINT16(screen->getBasePtr(x, y)); screenFormat.colorToRGB(col, r, g, b); } - ((uint16 *)surf->pixels)[y * surf->w + x] = Graphics::RGBToColor<Graphics::ColorMasks<565> >(r, g, b); + *((uint16 *)surf->getBasePtr(x, y)) = Graphics::RGBToColor<Graphics::ColorMasks<565> >(r, g, b); } } @@ -135,78 +210,20 @@ static bool grabScreen565(Graphics::Surface *surf) { } static bool createThumbnail(Graphics::Surface &out, Graphics::Surface &in) { - uint16 width = in.w; - uint16 inHeight = in.h; - - if (width < 320) { - // Special case to handle MM NES (uses a screen width of 256) - width = 320; - - // center MM NES screen - Graphics::Surface newscreen; - newscreen.create(width, in.h, in.format); - - uint8 *dst = (uint8 *)newscreen.getBasePtr((320 - in.w) / 2, 0); - const uint8 *src = (const uint8 *)in.getBasePtr(0, 0); - uint16 height = in.h; - - while (height--) { - memcpy(dst, src, in.pitch); - dst += newscreen.pitch; - src += in.pitch; - } - - in.free(); - in = newscreen; - } else if (width == 720) { - // Special case to handle Hercules mode - // - // NOTE: This code is pretty SCUMM specific. - // For other games this code might cut off - // not only the menu, but also other graphics. - width = 640; - inHeight = 400; - - // cut off menu and so on.. - Graphics::Surface newscreen; - newscreen.create(width, 400, in.format); - - uint8 *dst = (uint8 *)newscreen.getBasePtr(0, (400 - 240) / 2); - const uint8 *src = (const uint8 *)in.getBasePtr(41, 28); - - for (int y = 0; y < 240; ++y) { - memcpy(dst, src, 640 * in.format.bytesPerPixel); - dst += newscreen.pitch; - src += in.pitch; - } - - in.free(); - in = newscreen; - } else if (width == 640 && inHeight == 440) { - // Special case to handle KQ6 Windows: resize the screen to 640x480, - // adding a black band in the bottom. - inHeight = 480; - - Graphics::Surface newscreen; - newscreen.create(width, 480, in.format); - - memcpy(newscreen.getBasePtr(0, 0), in.getBasePtr(0, 0), width * 440 * in.format.bytesPerPixel); - - in.free(); - in = newscreen; + int height; + if ((in.w == 320 && in.h == 200) || (in.w == 640 && in.h == 400)) { + height = kThumbnailHeight1; + } else { + height = kThumbnailHeight2; } - uint16 newHeight = !(inHeight % 240) ? kThumbnailHeight2 : kThumbnailHeight1; - - out.create(kThumbnailWidth, newHeight, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)); - createThumbnail((const uint8 *)in.pixels, width * sizeof(uint16), (uint8 *)out.pixels, out.pitch, width, inHeight); - + out.create(kThumbnailWidth, height, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)); + scaleThumbnail(in, out); in.free(); - return true; } -bool createThumbnailFromScreen(Graphics::Surface* surf) { +bool createThumbnailFromScreen(Graphics::Surface *surf) { assert(surf); Graphics::Surface screen; @@ -230,9 +247,37 @@ bool createThumbnail(Graphics::Surface *surf, const uint8 *pixels, int w, int h, g = palette[pixels[y * w + x] * 3 + 1]; b = palette[pixels[y * w + x] * 3 + 2]; - ((uint16 *)screen.pixels)[y * screen.w + x] = Graphics::RGBToColor<Graphics::ColorMasks<565> >(r, g, b); + *((uint16 *)screen.getBasePtr(x, y)) = Graphics::RGBToColor<Graphics::ColorMasks<565> >(r, g, b); } } return createThumbnail(*surf, screen); } + +// this is somewhat awkward, but createScreenShot should logically be in graphics, +// but moving other functions in this file into that namespace breaks several engines +namespace Graphics { +bool createScreenShot(Graphics::Surface &surf) { + Graphics::PixelFormat screenFormat = g_system->getScreenFormat(); + //convert surface to 2 bytes pixel format to avoid problems with palette saving and loading + if ((screenFormat.bytesPerPixel == 1) || (screenFormat.bytesPerPixel == 2)) { + return grabScreen565(&surf); + } else { + Graphics::Surface *screen = g_system->lockScreen(); + if (!screen) { + return false; + } + surf.create(screen->w, screen->h, Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)); + for (uint y = 0; y < screen->h; ++y) { + for (uint x = 0; x < screen->w; ++x) { + byte r = 0, g = 0, b = 0, a = 0; + uint32 col = READ_UINT32(screen->getBasePtr(x, y)); + screenFormat.colorToARGB(col, a, r, g, b); + *((uint32 *)surf.getBasePtr(x, y)) = Graphics::ARGBToColor<Graphics::ColorMasks<8888> >(a, r, g, b); + } + } + g_system->unlockScreen(); + return true; + } +} +} // End of namespace Graphics diff --git a/graphics/surface.cpp b/graphics/surface.cpp index 41ae8dcebb..929157203e 100644 --- a/graphics/surface.cpp +++ b/graphics/surface.cpp @@ -82,9 +82,55 @@ void Surface::free() { format = PixelFormat(); } +void Surface::init(uint16 width, uint16 height, uint16 newPitch, void *newPixels, const PixelFormat &f) { + w = width; + h = height; + pitch = newPitch; + pixels = newPixels; + format = f; +} + void Surface::copyFrom(const Surface &surf) { create(surf.w, surf.h, surf.format); - memcpy(pixels, surf.pixels, h * pitch); + if (surf.pitch == pitch) { + memcpy(pixels, surf.pixels, h * pitch); + } else { + const byte *src = (const byte *)surf.pixels; + byte *dst = (byte *)pixels; + for (int y = h; y > 0; --y) { + memcpy(dst, src, w * format.bytesPerPixel); + src += surf.pitch; + dst += pitch; + } + } +} + +Surface Surface::getSubArea(const Common::Rect &area) { + Common::Rect effectiveArea(area); + effectiveArea.clip(w, h); + + Surface subSurface; + subSurface.w = effectiveArea.width(); + subSurface.h = effectiveArea.height(); + subSurface.pitch = pitch; + subSurface.pixels = getBasePtr(area.left, area.top); + subSurface.format = format; + return subSurface; +} + +const Surface Surface::getSubArea(const Common::Rect &area) const { + Common::Rect effectiveArea(area); + effectiveArea.clip(w, h); + + Surface subSurface; + subSurface.w = effectiveArea.width(); + subSurface.h = effectiveArea.height(); + subSurface.pitch = pitch; + // We need to cast the const away here because a Surface always has a + // pointer to modifiable pixel data. + subSurface.pixels = const_cast<void *>(getBasePtr(area.left, area.top)); + subSurface.format = format; + return subSurface; } void Surface::hLine(int x, int y, int x2, uint32 color) { diff --git a/graphics/surface.h b/graphics/surface.h index 6c9e464657..b08d4a5cb7 100644 --- a/graphics/surface.h +++ b/graphics/surface.h @@ -61,11 +61,13 @@ struct Surface { */ uint16 pitch; +protected: /** * The surface's pixel data. */ void *pixels; +public: /** * The pixel format of the surface. */ @@ -78,6 +80,33 @@ struct Surface { } /** + * Return a pointer to the pixel data. + * + * @return Pointer to the pixel data. + */ + inline const void *getPixels() const { + return pixels; + } + + /** + * Return a pointer to the pixel data. + * + * @return Pointer to the pixel data. + */ + inline void *getPixels() { + return pixels; + } + + /** + * Sets the pixel data. + * + * Note that this is a simply a setter. Be careful what you are doing! + * + * @param newPixels The new pixel data. + */ + void setPixels(void *newPixels) { pixels = newPixels; } + + /** * Return a pointer to the pixel at the specified point. * * @param x The x coordinate of the pixel. @@ -122,6 +151,20 @@ struct Surface { void free(); /** + * Set up the Surface with user specified data. + * + * Note that this simply sets the 'internal' attributes of the Surface. It + * will not take care of freeing old data via free or similar! + * + * @param width Width of the pixel data. + * @param height Height of the pixel data. + * @param pitch The pitch of the pixel data. + * @param pixels The pixel data itself. + * @param format The pixel format of the pixel data. + */ + void init(uint16 width, uint16 height, uint16 pitch, void *pixels, const PixelFormat &format); + + /** * Copy the data from another Surface. * * Note that this calls free on the current surface, to assure it being @@ -135,10 +178,42 @@ struct Surface { void copyFrom(const Surface &surf); /** + * Creates a Surface which represents a sub-area of this Surface object. + * + * The pixel (0, 0) of the returned Surface will be the same as Pixel + * (area.x, area.y) of this Surface. Changes to any of the Surface objects + * will change the shared pixel data. + * + * Note that the Surface returned is only valid as long as this Surface + * object is still alive (i.e. its pixel data is not destroyed or + * reallocated). Do *never* try to free the returned Surface. + * + * @param area The area which should be represented. Note that the area + * will get clipped in case it does not fit! + */ + Surface getSubArea(const Common::Rect &area); + + /** + * Creates a Surface which represents a sub-area of this Surface object. + * + * The pixel (0, 0) of the returned Surface will be the same as Pixel + * (area.x, area.y) of this Surface. + * + * Note that the Surface returned is only valid as long as this Surface + * object is still alive (i.e. its pixel data is not destroyed or + * reallocated). Do *never* try to free the returned Surface. + * + * @param area The area which should be represented. Note that the area + * will get clipped in case it does not fit! + */ + const Surface getSubArea(const Common::Rect &area) const; + + /** * Convert the data to another pixel format. * * This works in-place. This means it will not create an additional buffer - * for the conversion process. The value of pixels might change though. + * for the conversion process. The value of 'pixels' might change though + * (that means it might realloc the pixel data). * * Note that you should only use this, when you created the Surface data via * create! Otherwise this function has undefined behavior. diff --git a/graphics/thumbnail.cpp b/graphics/thumbnail.cpp index ddb377306d..e3f368dffa 100644 --- a/graphics/thumbnail.cpp +++ b/graphics/thumbnail.cpp @@ -23,6 +23,7 @@ #include "graphics/scaler.h" #include "graphics/colormasks.h" #include "common/endian.h" +#include "common/algorithm.h" #include "common/system.h" #include "common/stream.h" #include "common/textconsole.h" @@ -42,7 +43,16 @@ struct ThumbnailHeader { #define ThumbnailHeaderSize (4+4+1+2+2+(1+4+4)) -bool loadHeader(Common::SeekableReadStream &in, ThumbnailHeader &header, bool outputWarnings) { +enum HeaderState { + /// There is no header present + kHeaderNone, + /// The header present only has reliable values for version and size + kHeaderUnsupported, + /// The header is present and the version is supported + kHeaderPresent +}; + +HeaderState loadHeader(Common::SeekableReadStream &in, ThumbnailHeader &header, bool outputWarnings) { header.type = in.readUint32BE(); // We also accept the bad 'BMHT' header here, for the sake of compatibility // with some older savegames which were written incorrectly due to a bug in @@ -50,16 +60,28 @@ bool loadHeader(Common::SeekableReadStream &in, ThumbnailHeader &header, bool ou if (header.type != MKTAG('T','H','M','B') && header.type != MKTAG('B','M','H','T')) { if (outputWarnings) warning("couldn't find thumbnail header type"); - return false; + return kHeaderNone; } header.size = in.readUint32BE(); header.version = in.readByte(); + // Do a check whether any read errors had occured. If so we cannot use the + // values obtained for size and version because they might be bad. + if (in.err() || in.eos()) { + // TODO: We fake that there is no header. This is actually not quite + // correct since we found the start of the header and then things + // started to break. Right no we leave detection of this to the client. + // Since this case is caused by broken files, the client code should + // catch it anyway... If there is a nicer solution here, we should + // implement it. + return kHeaderNone; + } + if (header.version > THMB_VERSION) { if (outputWarnings) warning("trying to load a newer thumbnail version: %d instead of %d", header.version, THMB_VERSION); - return false; + return kHeaderUnsupported; } header.width = in.readUint16BE(); @@ -81,7 +103,15 @@ bool loadHeader(Common::SeekableReadStream &in, ThumbnailHeader &header, bool ou header.format = createPixelFormat<565>(); } - return true; + if (in.err() || in.eos()) { + // When we reached this point we know that at least the size and + // version field was loaded successfully, thus we tell this header + // is not supported and silently hope that the client code is + // prepared to handle read errors. + return kHeaderUnsupported; + } else { + return kHeaderPresent; + } } } // end of anonymous namespace @@ -89,7 +119,12 @@ bool checkThumbnailHeader(Common::SeekableReadStream &in) { uint32 position = in.pos(); ThumbnailHeader header; - bool hasHeader = loadHeader(in, header, false); + // TODO: It is not clear whether this is the best semantics. Now + // checkThumbnailHeader will return true even when the thumbnail header + // found is actually not usable. However, most engines seem to use this + // to detect the presence of any header and if there is none it wont even + // try to skip it. Thus, this looks like the best solution for now... + bool hasHeader = (loadHeader(in, header, false) != kHeaderNone); in.seek(position, SEEK_SET); @@ -100,7 +135,9 @@ bool skipThumbnail(Common::SeekableReadStream &in) { uint32 position = in.pos(); ThumbnailHeader header; - if (!loadHeader(in, header, false)) { + // We can skip unsupported and supported headers. So we only seek back + // to the old position in case there is no header at all. + if (loadHeader(in, header, false) == kHeaderNone) { in.seek(position, SEEK_SET); return false; } @@ -110,10 +147,23 @@ bool skipThumbnail(Common::SeekableReadStream &in) { } Graphics::Surface *loadThumbnail(Common::SeekableReadStream &in) { + const uint32 position = in.pos(); ThumbnailHeader header; - - if (!loadHeader(in, header, true)) + HeaderState headerState = loadHeader(in, header, true); + + // Try to handle unsupported/broken headers gracefully. If there is no + // header at all, we seek back and return at this point. If there is an + // unsupported/broken header, we skip the actual data and return. The + // downside is that we might reset the end of stream flag with this and + // the client code would not be able to notice a read past the end of the + // stream at this point then. + if (headerState == kHeaderNone) { + in.seek(position, SEEK_SET); + return 0; + } else if (headerState == kHeaderUnsupported) { + in.seek(header.size - (in.pos() - position), SEEK_CUR); return 0; + } if (header.format.bytesPerPixel != 2 && header.format.bytesPerPixel != 4) { warning("trying to load thumbnail with unsupported bit depth %d", header.format.bytesPerPixel); @@ -143,7 +193,6 @@ Graphics::Surface *loadThumbnail(Common::SeekableReadStream &in) { assert(0); } } - return to; } @@ -216,4 +265,55 @@ bool saveThumbnail(Common::WriteStream &out, const Graphics::Surface &thumb) { return true; } + +/** + * Returns an array indicating which pixels of a source image horizontally or vertically get + * included in a scaled image + */ +int *scaleLine(int size, int srcSize) { + int scale = 100 * size / srcSize; + assert(scale > 0); + int *v = new int[size]; + Common::fill(v, &v[size], 0); + + int distCtr = 0; + int *destP = v; + for (int distIndex = 0; distIndex < srcSize; ++distIndex) { + distCtr += scale; + while (distCtr >= 100) { + assert(destP < &v[size]); + *destP++ = distIndex; + distCtr -= 100; + } + } + + return v; +} + +Graphics::Surface *scale(const Graphics::Surface &srcImage, int xSize, int ySize) { + Graphics::Surface *s = new Graphics::Surface(); + s->create(xSize, ySize, srcImage.format); + + int *horizUsage = scaleLine(xSize, srcImage.w); + int *vertUsage = scaleLine(ySize, srcImage.h); + + // Loop to create scaled version + for (int yp = 0; yp < ySize; ++yp) { + const byte *srcP = (const byte *)srcImage.getBasePtr(0, vertUsage[yp]); + byte *destP = (byte *)s->getBasePtr(0, yp); + + for (int xp = 0; xp < xSize; ++xp) { + const byte *tempSrcP = srcP + (horizUsage[xp] * srcImage.format.bytesPerPixel); + for (int byteCtr = 0; byteCtr < srcImage.format.bytesPerPixel; ++byteCtr) { + *destP++ = *tempSrcP++; + } + } + } + + // Delete arrays and return surface + delete[] horizUsage; + delete[] vertUsage; + return s; +} + } // End of namespace Graphics diff --git a/graphics/thumbnail.h b/graphics/thumbnail.h index 45a0fdbf07..c857809c91 100644 --- a/graphics/thumbnail.h +++ b/graphics/thumbnail.h @@ -64,6 +64,24 @@ bool saveThumbnail(Common::WriteStream &out); */ bool saveThumbnail(Common::WriteStream &out, const Graphics::Surface &thumb); +/** + * Grabs framebuffer into surface + * + * @param surf a surface + * @return false if a error occurred + */ +bool createScreenShot(Graphics::Surface &surf); + +/** + * Scales a passed surface, creating a new surface with the result + * @param srcImage Source image to scale + * @param xSize New surface width + * @param ySize New surface height + * @remarks Caller is responsible for freeing the returned surface + */ +Graphics::Surface *scale(const Graphics::Surface &srcImage, int xSize, int ySize); + + } // End of namespace Graphics #endif diff --git a/graphics/yuv_to_rgb.cpp b/graphics/yuv_to_rgb.cpp index 6043315a13..2a485fa664 100644 --- a/graphics/yuv_to_rgb.cpp +++ b/graphics/yuv_to_rgb.cpp @@ -229,7 +229,7 @@ void convertYUV444ToRGB(byte *dstPtr, int dstPitch, const YUVToRGBLookup *lookup void YUVToRGBManager::convert444(Graphics::Surface *dst, YUVToRGBManager::LuminanceScale scale, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) { // Sanity checks - assert(dst && dst->pixels); + assert(dst && dst->getPixels()); assert(dst->format.bytesPerPixel == 2 || dst->format.bytesPerPixel == 4); assert(ySrc && uSrc && vSrc); @@ -237,9 +237,9 @@ void YUVToRGBManager::convert444(Graphics::Surface *dst, YUVToRGBManager::Lumina // Use a templated function to avoid an if check on every pixel if (dst->format.bytesPerPixel == 2) - convertYUV444ToRGB<uint16>((byte *)dst->pixels, dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch); + convertYUV444ToRGB<uint16>((byte *)dst->getPixels(), dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch); else - convertYUV444ToRGB<uint32>((byte *)dst->pixels, dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch); + convertYUV444ToRGB<uint32>((byte *)dst->getPixels(), dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch); } template<typename PixelInt> @@ -283,7 +283,7 @@ void convertYUV420ToRGB(byte *dstPtr, int dstPitch, const YUVToRGBLookup *lookup void YUVToRGBManager::convert420(Graphics::Surface *dst, YUVToRGBManager::LuminanceScale scale, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) { // Sanity checks - assert(dst && dst->pixels); + assert(dst && dst->getPixels()); assert(dst->format.bytesPerPixel == 2 || dst->format.bytesPerPixel == 4); assert(ySrc && uSrc && vSrc); assert((yWidth & 1) == 0); @@ -293,9 +293,9 @@ void YUVToRGBManager::convert420(Graphics::Surface *dst, YUVToRGBManager::Lumina // Use a templated function to avoid an if check on every pixel if (dst->format.bytesPerPixel == 2) - convertYUV420ToRGB<uint16>((byte *)dst->pixels, dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch); + convertYUV420ToRGB<uint16>((byte *)dst->getPixels(), dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch); else - convertYUV420ToRGB<uint32>((byte *)dst->pixels, dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch); + convertYUV420ToRGB<uint32>((byte *)dst->getPixels(), dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch); } #define READ_QUAD(ptr, prefix) \ @@ -368,7 +368,7 @@ void convertYUV410ToRGB(byte *dstPtr, int dstPitch, const YUVToRGBLookup *lookup void YUVToRGBManager::convert410(Graphics::Surface *dst, YUVToRGBManager::LuminanceScale scale, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) { // Sanity checks - assert(dst && dst->pixels); + assert(dst && dst->getPixels()); assert(dst->format.bytesPerPixel == 2 || dst->format.bytesPerPixel == 4); assert(ySrc && uSrc && vSrc); assert((yWidth & 3) == 0); @@ -378,9 +378,9 @@ void YUVToRGBManager::convert410(Graphics::Surface *dst, YUVToRGBManager::Lumina // Use a templated function to avoid an if check on every pixel if (dst->format.bytesPerPixel == 2) - convertYUV410ToRGB<uint16>((byte *)dst->pixels, dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch); + convertYUV410ToRGB<uint16>((byte *)dst->getPixels(), dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch); else - convertYUV410ToRGB<uint32>((byte *)dst->pixels, dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch); + convertYUV410ToRGB<uint32>((byte *)dst->getPixels(), dst->pitch, lookup, _colorTab, ySrc, uSrc, vSrc, yWidth, yHeight, yPitch, uvPitch); } } // End of namespace Graphics diff --git a/graphics/yuv_to_rgb.h b/graphics/yuv_to_rgb.h index f785422c5a..a1e61ec705 100644 --- a/graphics/yuv_to_rgb.h +++ b/graphics/yuv_to_rgb.h @@ -22,10 +22,17 @@ /** * @file - * YUV to RGB conversion used in engines: - * - mohawk - * - scumm (he) - * - sword25 + * YUV to RGB conversion. + * + * Used in graphics: + * - JPEGDecoder + * + * Used in video: + * - BinkDecoder + * - Indeo3Decoder + * - PSXStreamDecoder + * - TheoraDecoder + * - SVQ1Decoder */ #ifndef GRAPHICS_YUV_TO_RGB_H |