GRAPHICS: Add a function for scaling a standard Graphics::Surface

This also makes use of it in the SCI and Wintermute engines
This commit is contained in:
Cameron Cawley 2020-07-05 22:17:03 +01:00 committed by Eugene Sandulenko
parent ff1474591f
commit 352653b8a2
8 changed files with 40 additions and 37 deletions

View file

@ -30,7 +30,6 @@
#include "common/system.h" // for g_system
#include "engines/engine.h" // for Engine, g_engine
#include "graphics/palette.h" // for PaletteManager
#include "graphics/transparent_surface.h" // for TransparentSurface
#include "sci/console.h" // for Console
#include "sci/engine/features.h" // for GameFeatures
#include "sci/engine/state.h" // for EngineState
@ -242,20 +241,16 @@ void VideoPlayer::renderFrame(const Graphics::Surface &nextFrame) const {
if (_decoder->getWidth() != _drawRect.width() || _decoder->getHeight() != _drawRect.height()) {
Graphics::Surface *const unscaledFrame(convertedFrame);
// TODO: The only reason TransparentSurface is used here because it is
// where common scaler code is right now, which should just be part of
// Graphics::Surface (or some free functions).
const Graphics::TransparentSurface tsUnscaledFrame(*unscaledFrame);
#ifdef USE_RGB_COLOR
if (_hqVideoMode) {
convertedFrame = tsUnscaledFrame.scaleT<Graphics::FILTER_BILINEAR>(_drawRect.width(), _drawRect.height());
convertedFrame = unscaledFrame->scale(_drawRect.width(), _drawRect.height(), true);
} else {
#elif 1
{
#else
}
#endif
convertedFrame = tsUnscaledFrame.scaleT<Graphics::FILTER_NEAREST>(_drawRect.width(), _drawRect.height());
convertedFrame = unscaledFrame->scale(_drawRect.width(), _drawRect.height(), false);
}
assert(convertedFrame);
if (freeConvertedFrame) {

View file

@ -36,7 +36,6 @@
#include "engines/wintermute/base/gfx/base_image.h"
#include "engines/wintermute/base/save_thumb_helper.h"
#include "engines/wintermute/base/sound/base_sound.h"
#include "graphics/transparent_surface.h"
#include "engines/wintermute/wintermute.h"
#include "graphics/scaler.h"
#include "image/bmp.h"
@ -173,11 +172,9 @@ void BasePersistenceManager::getSaveStateDesc(int slot, SaveStateDescriptor &des
Image::BitmapDecoder bmpDecoder;
if (bmpDecoder.loadStream(thumbStream)) {
const Graphics::Surface *bmpSurface = bmpDecoder.getSurface();
Graphics::TransparentSurface *scaleableSurface = new Graphics::TransparentSurface(*bmpSurface, false);
Graphics::Surface *scaled = scaleableSurface->scale(kThumbnailWidth, kThumbnailHeight2);
Graphics::Surface *scaled = bmpSurface->scale(kThumbnailWidth, kThumbnailHeight2);
Graphics::Surface *thumb = scaled->convertTo(g_system->getOverlayFormat());
desc.setThumbnail(thumb);
delete scaleableSurface;
scaled->free();
delete scaled;
}

View file

@ -28,7 +28,6 @@
#include "engines/wintermute/base/gfx/base_image.h"
#include "engines/wintermute/base/base_file_manager.h"
#include "graphics/transparent_surface.h"
#include "graphics/surface.h"
#include "image/png.h"
#include "image/jpeg.h"
@ -112,14 +111,13 @@ bool BaseImage::saveBMPFile(const Common::String &filename) const {
//////////////////////////////////////////////////////////////////////////
bool BaseImage::resize(int newWidth, int newHeight) {
// WME Lite used FILTER_BILINEAR with FreeImage_Rescale here.
Graphics::TransparentSurface temp(*_surface, true);
Graphics::Surface *temp = _surface->scale((uint16)newWidth, (uint16)newHeight);
if (_deletableSurface) {
_deletableSurface->free();
delete _deletableSurface;
_deletableSurface = nullptr;
}
_surface = _deletableSurface = temp.scale((uint16)newWidth, (uint16)newHeight);
temp.free();
_surface = _deletableSurface = temp;
return true;
}
@ -216,13 +214,13 @@ bool BaseImage::writeBMPToStream(Common::WriteStream *stream) const {
bool BaseImage::copyFrom(BaseImage *origImage, int newWidth, int newHeight) {
// WME Lite used FILTER_BILINEAR with FreeImage_Rescale here.
Graphics::TransparentSurface temp(*origImage->_surface, false);
Graphics::Surface *temp = origImage->_surface->scale((uint16)newWidth, (uint16)newHeight);
if (_deletableSurface) {
_deletableSurface->free();
delete _deletableSurface;
_deletableSurface = nullptr;
}
_surface = _deletableSurface = temp.scale((uint16)newWidth, (uint16)newHeight);
_surface = _deletableSurface = temp;
return true;
}

View file

@ -72,13 +72,7 @@ RenderTicket::RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *s
} else if ((dstRect->width() != srcRect->width() ||
dstRect->height() != srcRect->height()) &&
_transform._numTimesX * _transform._numTimesY == 1) {
Graphics::TransparentSurface src(*_surface, false);
Graphics::Surface *temp;
if (owner->_gameRef->getBilinearFiltering()) {
temp = src.scaleT<Graphics::FILTER_BILINEAR>(dstRect->width(), dstRect->height());
} else {
temp = src.scaleT<Graphics::FILTER_NEAREST>(dstRect->width(), dstRect->height());
}
Graphics::Surface *temp = _surface->scale(dstRect->width(), dstRect->height(), owner->_gameRef->getBilinearFiltering());
_surface->free();
delete _surface;
_surface = temp;

View file

@ -368,6 +368,21 @@ void Surface::flipVertical(const Common::Rect &r) {
delete[] temp;
}
Graphics::Surface *Surface::scale(uint16 newWidth, uint16 newHeight, bool filtering) const {
Graphics::Surface *target = new Graphics::Surface();
target->create(newWidth, newHeight, format);
if (filtering) {
scaleBlitBilinear((byte *)target->getPixels(), (const byte *)getPixels(), target->pitch, pitch, target->w, target->h, w, h, format);
} else {
scaleBlit((byte *)target->getPixels(), (const byte *)getPixels(), target->pitch, pitch, target->w, target->h, w, h, format);
}
return target;
}
void Surface::convertToInPlace(const PixelFormat &dstFormat, const byte *palette) {
// Do not convert to the same format and ignore empty surfaces.
if (format == dstFormat || pixels == 0) {

View file

@ -334,6 +334,19 @@ public:
* @param r Rect to flip
*/
void flipVertical(const Common::Rect &r);
/**
* Scale the data to the given size.
*
* The calling code must call free on the returned surface and then delete
* it.
*
* @param newWidth the resulting width.
* @param newHeight the resulting height.
* @param filtering Whether or not to use bilinear filtering.
*/
Graphics::Surface *scale(uint16 newWidth, uint16 newHeight, bool filtering = false) const;
};
/**

View file

@ -909,14 +909,13 @@ TransparentSurface *TransparentSurface::rotoscaleT(const TransformStruct &transf
return target;
}
template <TFilteringMode filteringMode>
TransparentSurface *TransparentSurface::scaleT(uint16 newWidth, uint16 newHeight) const {
TransparentSurface *TransparentSurface::scale(uint16 newWidth, uint16 newHeight, bool filtering) const {
TransparentSurface *target = new TransparentSurface();
target->create(newWidth, newHeight, format);
if (filteringMode == FILTER_BILINEAR) {
if (filtering) {
scaleBlitBilinear((byte *)target->getPixels(), (const byte *)getPixels(), target->pitch, pitch, target->w, target->h, w, h, format);
} else {
scaleBlit((byte *)target->getPixels(), (const byte *)getPixels(), target->pitch, pitch, target->w, target->h, w, h, format);
@ -1005,15 +1004,9 @@ TransparentSurface *TransparentSurface::convertTo(const PixelFormat &dstFormat,
template TransparentSurface *TransparentSurface::rotoscaleT<FILTER_NEAREST>(const TransformStruct &transform) const;
template TransparentSurface *TransparentSurface::rotoscaleT<FILTER_BILINEAR>(const TransformStruct &transform) const;
template TransparentSurface *TransparentSurface::scaleT<FILTER_NEAREST>(uint16 newWidth, uint16 newHeight) const;
template TransparentSurface *TransparentSurface::scaleT<FILTER_BILINEAR>(uint16 newWidth, uint16 newHeight) const;
TransparentSurface *TransparentSurface::rotoscale(const TransformStruct &transform) const {
return rotoscaleT<FILTER_BILINEAR>(transform);
}
TransparentSurface *TransparentSurface::scale(uint16 newWidth, uint16 newHeight) const {
return scaleT<FILTER_NEAREST>(newWidth, newHeight);
}
} // End of namespace Graphics

View file

@ -145,12 +145,10 @@ struct TransparentSurface : public Graphics::Surface {
*
* @param newWidth the resulting width.
* @param newHeight the resulting height.
* @param filtering Whether or not to use bilinear filtering.
* @see TransformStruct
*/
template <TFilteringMode filteringMode>
TransparentSurface *scaleT(uint16 newWidth, uint16 newHeight) const;
TransparentSurface *scale(uint16 newWidth, uint16 newHeight) const;
TransparentSurface *scale(uint16 newWidth, uint16 newHeight, bool filtering = false) const;
/**
* @brief Rotoscale function; this returns a transformed version of this surface after rotation and