From cd453b3d0195f3a95b1df25c24cca0e347a66082 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 14 Sep 2010 20:09:41 +0000 Subject: SWORD25: Rename glimage.* to renderedimage.* svn-id: r53360 --- engines/sword25/gfx/image/renderedimage.cpp | 394 ++++++++++++++++++++++++++++ 1 file changed, 394 insertions(+) create mode 100644 engines/sword25/gfx/image/renderedimage.cpp (limited to 'engines/sword25/gfx/image/renderedimage.cpp') diff --git a/engines/sword25/gfx/image/renderedimage.cpp b/engines/sword25/gfx/image/renderedimage.cpp new file mode 100644 index 0000000000..104e147e43 --- /dev/null +++ b/engines/sword25/gfx/image/renderedimage.cpp @@ -0,0 +1,394 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +/* + * This code is based on Broken Sword 2.5 engine + * + * Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdoerfer + * + * Licensed under GNU GPL v2 + * + */ + +// ----------------------------------------------------------------------------- +// INCLUDES +// ----------------------------------------------------------------------------- + +#include "sword25/package/packagemanager.h" +#include "sword25/gfx/image/imageloader.h" +#include "sword25/gfx/image/glimage.h" + +#include "common/system.h" + +namespace Sword25 { + +#define BS_LOG_PREFIX "GLIMAGE" + +// ----------------------------------------------------------------------------- +// CONSTRUCTION / DESTRUCTION +// ----------------------------------------------------------------------------- + +GLImage::GLImage(const Common::String &filename, bool &result) : + _data(0), + _width(0), + _height(0) { + result = false; + + PackageManager *pPackage = static_cast(Kernel::GetInstance()->GetService("package")); + BS_ASSERT(pPackage); + + _backSurface = (static_cast(Kernel::GetInstance()->GetService("gfx")))->getSurface(); + + // Datei laden + byte *pFileData; + uint fileSize; + if (!(pFileData = (byte *)pPackage->GetFile(filename, &fileSize))) { + BS_LOG_ERRORLN("File \"%s\" could not be loaded.", filename.c_str()); + return; + } + + // Bildeigenschaften bestimmen + GraphicEngine::COLOR_FORMATS colorFormat; + int pitch; + if (!ImageLoader::ExtractImageProperties(pFileData, fileSize, colorFormat, _width, _height)) { + BS_LOG_ERRORLN("Could not read image properties."); + delete[] pFileData; + return; + } + + // Das Bild dekomprimieren + if (!ImageLoader::LoadImage(pFileData, fileSize, GraphicEngine::CF_ARGB32, _data, _width, _height, pitch)) { + BS_LOG_ERRORLN("Could not decode image."); + delete[] pFileData; + return; + } + + // Dateidaten freigeben + delete[] pFileData; + + _doCleanup = true; + + result = true; + return; +} + +// ----------------------------------------------------------------------------- + +GLImage::GLImage(uint width, uint height, bool &result) : + _width(width), + _height(height) { + + _data = new byte[width * height * 4]; + Common::set_to(_data, &_data[width * height * 4], 0); + + _backSurface = (static_cast(Kernel::GetInstance()->GetService("gfx")))->getSurface(); + + _doCleanup = true; + + result = true; + return; +} + +GLImage::GLImage() : _width(0), _height(0), _data(0) { + _backSurface = (static_cast(Kernel::GetInstance()->GetService("gfx")))->getSurface(); + + _doCleanup = false; + + return; +} + +// ----------------------------------------------------------------------------- + +GLImage::~GLImage() { + if (_doCleanup) + delete[] _data; +} + +// ----------------------------------------------------------------------------- + +bool GLImage::fill(const Common::Rect *pFillRect, uint color) { + BS_LOG_ERRORLN("Fill() is not supported."); + return false; +} + +// ----------------------------------------------------------------------------- + +bool GLImage::setContent(const byte *pixeldata, uint size, uint offset, uint stride) { + // Überprüfen, ob PixelData ausreichend viele Pixel enthält um ein Bild der Größe Width * Height zu erzeugen + if (size < static_cast(_width * _height * 4)) { + BS_LOG_ERRORLN("PixelData vector is too small to define a 32 bit %dx%d image.", _width, _height); + return false; + } + + const byte *in = &pixeldata[offset]; + byte *out = _data; + + for (int i = 0; i < _height; i++) { + memcpy(out, in, _width * 4); + out += _width * 4; + in += stride; + } + + return true; +} + +void GLImage::replaceContent(byte *pixeldata, int width, int height) { + _width = width; + _height = height; + _data = pixeldata; +} +// ----------------------------------------------------------------------------- + +uint GLImage::getPixel(int x, int y) { + BS_LOG_ERRORLN("GetPixel() is not supported. Returning black."); + return 0; +} + +// ----------------------------------------------------------------------------- + +bool GLImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRect, uint color, int width, int height) { + int ca = (color >> 24) & 0xff; + + // Check if we need to draw anything at all + if (ca == 0) + return true; + + int cr = (color >> 16) & 0xff; + int cg = (color >> 8) & 0xff; + int cb = (color >> 0) & 0xff; + + // Compensate for transparency. Since we're coming + // down to 255 alpha, we just compensate for the colors here + if (ca != 255) { + cr = cr * ca >> 8; + cg = cg * ca >> 8; + cb = cb * ca >> 8; + } + + // Create an encapsulating surface for the data + Graphics::Surface srcImage; + srcImage.bytesPerPixel = 4; + srcImage.pitch = _width * 4; + srcImage.w = _width; + srcImage.h = _height; + srcImage.pixels = _data; + + if (pPartRect) { + srcImage.pixels = &_data[pPartRect->top * srcImage.pitch + pPartRect->left * 4]; + srcImage.w = pPartRect->right - pPartRect->left; + srcImage.h = pPartRect->bottom - pPartRect->top; + + debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping, + pPartRect->left, pPartRect->top, pPartRect->width(), pPartRect->height(), color, width, height); + } else { + + debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping, 0, 0, + srcImage.w, srcImage.h, color, width, height); + } + + if (width == -1) + width = srcImage.w; + if (height == -1) + height = srcImage.h; + +#ifdef SCALING_TESTING + // Hardcode scaling to 66% to test scaling + width = width * 2 / 3; + height = height * 2 / 3; +#endif + + Graphics::Surface *img; + Graphics::Surface *imgScaled = NULL; + byte *savedPixels = NULL; + if ((width != srcImage.w) || (height != srcImage.h)) { + // Scale the image + img = imgScaled = scale(srcImage, width, height); + savedPixels = (byte *)img->pixels; + } else { + img = &srcImage; + } + + // Handle off-screen clipping + if (posY < 0) { + img->h = MAX(0, (int)img->h - -posY); + img->pixels = (byte *)img->pixels + img->pitch * -posY; + posY = 0; + } + + if (posX < 0) { + img->w = MAX(0, (int)img->w - -posX); + img->pixels = (byte *)img->pixels + (-posX * 4); + posX = 0; + } + + img->w = CLIP((int)img->w, 0, (int)MAX((int)_backSurface->w - posX, 0)); + img->h = CLIP((int)img->h, 0, (int)MAX((int)_backSurface->h - posY, 0)); + + if ((img->w > 0) && (img->h > 0)) { + int xp = 0, yp = 0; + + int inStep = 4; + int inoStep = img->pitch; + if (flipping & Image::FLIP_V) { + inStep = -inStep; + xp = img->w - 1; + } + + if (flipping & Image::FLIP_H) { + inoStep = -inoStep; + yp = img->h - 1; + } + + byte *ino = (byte *)img->getBasePtr(xp, yp); + byte *outo = (byte *)_backSurface->getBasePtr(posX, posY); + byte *in, *out; + + for (int i = 0; i < img->h; i++) { + out = outo; + in = ino; + for (int j = 0; j < img->w; j++) { + int r = in[0]; + int g = in[1]; + int b = in[2]; + int a = in[3]; + in += inStep; + + switch (a) { + case 0: // Full transparency + out += 4; + break; + case 255: // Full opacity + if (cr != 255) + *out++ = (r * cr) >> 8; + else + *out++ = r; + + if (cg != 255) + *out++ = (g * cg) >> 8; + else + *out++ = g; + + if (cb != 255) + *out++ = (b * cb) >> 8; + else + *out++ = b; + + *out++ = a; + break; + + default: // alpha blending + if (cr != 255) + *out += ((r - *out) * a * cr) >> 16; + else + *out += ((r - *out) * a) >> 8; + out++; + if (cg != 255) + *out += ((g - *out) * a * cg) >> 16; + else + *out += ((g - *out) * a) >> 8; + out++; + if (cb != 255) + *out += ((b - *out) * a * cb) >> 16; + else + *out += ((b - *out) * a) >> 8; + out++; + *out = 255; + out++; + } + } + outo += _backSurface->pitch; + ino += inoStep; + } + + g_system->copyRectToScreen((byte *)_backSurface->getBasePtr(posX, posY), _backSurface->pitch, posX, posY, + img->w, img->h); + } + + if (imgScaled) { + imgScaled->pixels = savedPixels; + imgScaled->free(); + delete imgScaled; + } + + return true; +} + +/** + * Scales a passed surface, creating a new surface with the result + * @param srcImage Source image to scale + * @param scaleFactor Scale amount. Must be between 0 and 1.0 (but not zero) + * @remarks Caller is responsible for freeing the returned surface + */ +Graphics::Surface *GLImage::scale(const Graphics::Surface &srcImage, int xSize, int ySize) { + Graphics::Surface *s = new Graphics::Surface(); + s->create(xSize, ySize, srcImage.bytesPerPixel); + + 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.bytesPerPixel); + for (int byteCtr = 0; byteCtr < srcImage.bytesPerPixel; ++byteCtr) { + *destP++ = *tempSrcP++; + } + } + } + + // Delete arrays and return surface + delete[] horizUsage; + delete[] vertUsage; + return s; +} + +/** + * Returns an array indicating which pixels of a source image horizontally or vertically get + * included in a scaled image + */ +int *GLImage::scaleLine(int size, int srcSize) { + int scale = 100 * size / srcSize; + assert(scale > 0); + int *v = new int[size]; + Common::set_to(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; +} + +} // End of namespace Sword25 -- cgit v1.2.3 From e975cc057d31f8c2daa422308ff3a6c1891b139c Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 14 Sep 2010 20:15:27 +0000 Subject: SWORD25: Rename GLImage to RenderedImage svn-id: r53361 --- engines/sword25/gfx/image/renderedimage.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'engines/sword25/gfx/image/renderedimage.cpp') diff --git a/engines/sword25/gfx/image/renderedimage.cpp b/engines/sword25/gfx/image/renderedimage.cpp index 104e147e43..5ba31c4835 100644 --- a/engines/sword25/gfx/image/renderedimage.cpp +++ b/engines/sword25/gfx/image/renderedimage.cpp @@ -38,19 +38,19 @@ #include "sword25/package/packagemanager.h" #include "sword25/gfx/image/imageloader.h" -#include "sword25/gfx/image/glimage.h" +#include "sword25/gfx/image/renderedimage.h" #include "common/system.h" namespace Sword25 { -#define BS_LOG_PREFIX "GLIMAGE" +#define BS_LOG_PREFIX "RENDEREDIMAGE" // ----------------------------------------------------------------------------- // CONSTRUCTION / DESTRUCTION // ----------------------------------------------------------------------------- -GLImage::GLImage(const Common::String &filename, bool &result) : +RenderedImage::RenderedImage(const Common::String &filename, bool &result) : _data(0), _width(0), _height(0) { @@ -96,7 +96,7 @@ GLImage::GLImage(const Common::String &filename, bool &result) : // ----------------------------------------------------------------------------- -GLImage::GLImage(uint width, uint height, bool &result) : +RenderedImage::RenderedImage(uint width, uint height, bool &result) : _width(width), _height(height) { @@ -111,7 +111,7 @@ GLImage::GLImage(uint width, uint height, bool &result) : return; } -GLImage::GLImage() : _width(0), _height(0), _data(0) { +RenderedImage::RenderedImage() : _width(0), _height(0), _data(0) { _backSurface = (static_cast(Kernel::GetInstance()->GetService("gfx")))->getSurface(); _doCleanup = false; @@ -121,21 +121,21 @@ GLImage::GLImage() : _width(0), _height(0), _data(0) { // ----------------------------------------------------------------------------- -GLImage::~GLImage() { +RenderedImage::~RenderedImage() { if (_doCleanup) delete[] _data; } // ----------------------------------------------------------------------------- -bool GLImage::fill(const Common::Rect *pFillRect, uint color) { +bool RenderedImage::fill(const Common::Rect *pFillRect, uint color) { BS_LOG_ERRORLN("Fill() is not supported."); return false; } // ----------------------------------------------------------------------------- -bool GLImage::setContent(const byte *pixeldata, uint size, uint offset, uint stride) { +bool RenderedImage::setContent(const byte *pixeldata, uint size, uint offset, uint stride) { // Überprüfen, ob PixelData ausreichend viele Pixel enthält um ein Bild der Größe Width * Height zu erzeugen if (size < static_cast(_width * _height * 4)) { BS_LOG_ERRORLN("PixelData vector is too small to define a 32 bit %dx%d image.", _width, _height); @@ -154,21 +154,21 @@ bool GLImage::setContent(const byte *pixeldata, uint size, uint offset, uint str return true; } -void GLImage::replaceContent(byte *pixeldata, int width, int height) { +void RenderedImage::replaceContent(byte *pixeldata, int width, int height) { _width = width; _height = height; _data = pixeldata; } // ----------------------------------------------------------------------------- -uint GLImage::getPixel(int x, int y) { +uint RenderedImage::getPixel(int x, int y) { BS_LOG_ERRORLN("GetPixel() is not supported. Returning black."); return 0; } // ----------------------------------------------------------------------------- -bool GLImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRect, uint color, int width, int height) { +bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRect, uint color, int width, int height) { int ca = (color >> 24) & 0xff; // Check if we need to draw anything at all @@ -341,7 +341,7 @@ bool GLImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRect, ui * @param scaleFactor Scale amount. Must be between 0 and 1.0 (but not zero) * @remarks Caller is responsible for freeing the returned surface */ -Graphics::Surface *GLImage::scale(const Graphics::Surface &srcImage, int xSize, int ySize) { +Graphics::Surface *RenderedImage::scale(const Graphics::Surface &srcImage, int xSize, int ySize) { Graphics::Surface *s = new Graphics::Surface(); s->create(xSize, ySize, srcImage.bytesPerPixel); @@ -371,7 +371,7 @@ Graphics::Surface *GLImage::scale(const Graphics::Surface &srcImage, int xSize, * Returns an array indicating which pixels of a source image horizontally or vertically get * included in a scaled image */ -int *GLImage::scaleLine(int size, int srcSize) { +int *RenderedImage::scaleLine(int size, int srcSize) { int scale = 100 * size / srcSize; assert(scale > 0); int *v = new int[size]; -- cgit v1.2.3 From 7c1b37e150e154a8259e8bc820c6af3ae2a5e7c9 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Mon, 20 Sep 2010 13:34:12 +0000 Subject: SWORD25: Fix transparency effects svn-id: r53375 --- engines/sword25/gfx/image/renderedimage.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'engines/sword25/gfx/image/renderedimage.cpp') diff --git a/engines/sword25/gfx/image/renderedimage.cpp b/engines/sword25/gfx/image/renderedimage.cpp index 5ba31c4835..e6afffe3b0 100644 --- a/engines/sword25/gfx/image/renderedimage.cpp +++ b/engines/sword25/gfx/image/renderedimage.cpp @@ -275,6 +275,10 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe int a = in[3]; in += inStep; + if (ca != 255) { + a = a * ca >> 8; + } + switch (a) { case 0: // Full transparency out += 4; -- cgit v1.2.3 From 8582c1ad5770b6385381f524a4610934d115cd88 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Sat, 25 Sep 2010 19:48:26 +0000 Subject: SWORD25: Enforse code naming conventions in PackageManager and Sword25Engine svn-id: r53380 --- engines/sword25/gfx/image/renderedimage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/sword25/gfx/image/renderedimage.cpp') diff --git a/engines/sword25/gfx/image/renderedimage.cpp b/engines/sword25/gfx/image/renderedimage.cpp index e6afffe3b0..96b6139a59 100644 --- a/engines/sword25/gfx/image/renderedimage.cpp +++ b/engines/sword25/gfx/image/renderedimage.cpp @@ -64,7 +64,7 @@ RenderedImage::RenderedImage(const Common::String &filename, bool &result) : // Datei laden byte *pFileData; uint fileSize; - if (!(pFileData = (byte *)pPackage->GetFile(filename, &fileSize))) { + if (!(pFileData = (byte *)pPackage->getFile(filename, &fileSize))) { BS_LOG_ERRORLN("File \"%s\" could not be loaded.", filename.c_str()); return; } -- cgit v1.2.3