[Scummvm-git-logs] scummvm master -> f5f445be5faa81185580dd66711f1b6dd9014d11
sev-
noreply at scummvm.org
Sun Apr 9 10:49:28 UTC 2023
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
f5f445be5f GRAPHICS: Add generic versions of applyColorKey() and setAlpha()
Commit: f5f445be5faa81185580dd66711f1b6dd9014d11
https://github.com/scummvm/scummvm/commit/f5f445be5faa81185580dd66711f1b6dd9014d11
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2023-04-09T12:49:23+02:00
Commit Message:
GRAPHICS: Add generic versions of applyColorKey() and setAlpha()
Changed paths:
A graphics/blit-alpha.cpp
engines/wintermute/base/gfx/opengl/base_surface_opengl3d.cpp
engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
graphics/blit.h
graphics/module.mk
graphics/surface.cpp
graphics/surface.h
graphics/transparent_surface.cpp
graphics/transparent_surface.h
diff --git a/engines/wintermute/base/gfx/opengl/base_surface_opengl3d.cpp b/engines/wintermute/base/gfx/opengl/base_surface_opengl3d.cpp
index 9fd64736486..0db36dc0d00 100644
--- a/engines/wintermute/base/gfx/opengl/base_surface_opengl3d.cpp
+++ b/engines/wintermute/base/gfx/opengl/base_surface_opengl3d.cpp
@@ -33,30 +33,6 @@
namespace Wintermute {
-void applyColorKey(Graphics::Surface &surf, byte ckRed, byte ckGreen, byte ckBlue, bool replaceAlpha) {
- // this is taken from Graphics::TransparentSurface
- // only difference is that we set the pixel
- // color to transparent black, like D3DX,
- // if it matches the color key
- for (int y = 0; y < surf.h; y++) {
- for (int x = 0; x < surf.w; x++) {
- uint32 pix = ((uint32 *)surf.getPixels())[y * surf.w + x];
- uint8 r, g, b, a;
- surf.format.colorToARGB(pix, a, r, g, b);
- if (r == ckRed && g == ckGreen && b == ckBlue) {
- a = 0;
- r = 0;
- g = 0;
- b = 0;
- ((uint32 *)surf.getPixels())[y * surf.w + x] = surf.format.ARGBToColor(a, r, g, b);
- } else if (replaceAlpha) {
- a = 255;
- ((uint32 *)surf.getPixels())[y * surf.w + x] = surf.format.ARGBToColor(a, r, g, b);
- }
- }
- }
-}
-
BaseSurfaceOpenGL3D::BaseSurfaceOpenGL3D(BaseGame *game, BaseRenderer3D *renderer)
: BaseSurface(game), _tex(0), _renderer(renderer), _imageData(nullptr), _texWidth(0), _texHeight(0) {
}
@@ -197,7 +173,9 @@ bool BaseSurfaceOpenGL3D::create(const Common::String &filename, bool defaultCK,
}
if (needsColorKey) {
- applyColorKey(*_imageData, ckRed, ckGreen, ckBlue, replaceAlpha);
+ // We set the pixel color to transparent black,
+ // like D3DX, if it matches the color key.
+ _imageData->applyColorKey(ckRed, ckGreen, ckBlue, replaceAlpha, 0, 0, 0);
}
putSurface(*_imageData);
diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
index 87dadcd1950..f5c7d975a7f 100644
--- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
+++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
@@ -185,8 +185,7 @@ bool BaseSurfaceOSystem::finishLoad() {
}
if (needsColorKey) {
- Graphics::TransparentSurface trans(*_surface);
- trans.applyColorKey(_ckRed, _ckGreen, _ckBlue, replaceAlpha);
+ _surface->applyColorKey(_ckRed, _ckGreen, _ckBlue, replaceAlpha);
}
_alphaType = hasTransparencyType(_surface);
diff --git a/graphics/blit-alpha.cpp b/graphics/blit-alpha.cpp
new file mode 100644
index 00000000000..01cff6d65a0
--- /dev/null
+++ b/graphics/blit-alpha.cpp
@@ -0,0 +1,170 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "graphics/blit.h"
+#include "graphics/pixelformat.h"
+
+namespace Graphics {
+
+namespace {
+
+template<typename Size, bool overwriteAlpha>
+inline void applyColorKeyLogic(byte *dst, const byte *src, const uint w, const uint h,
+ const uint srcDelta, const uint dstDelta,
+ const Graphics::PixelFormat &format,
+ const uint8 rKey, const uint8 gKey, const uint8 bKey,
+ const uint8 rNew, const uint8 gNew, const uint8 bNew) {
+
+ const uint32 keyPix = format.ARGBToColor(0, rKey, gKey, bKey);
+ const uint32 newPix = format.ARGBToColor(0, rNew, gNew, bNew);
+ const uint32 rgbMask = format.ARGBToColor(0, 255, 255, 255);
+ const uint32 alphaMask = format.ARGBToColor(255, 0, 0, 0);
+
+ for (uint y = 0; y < h; ++y) {
+ for (uint x = 0; x < w; ++x) {
+ uint32 pix = *(const Size *)src;
+
+ if ((pix & rgbMask) == keyPix) {
+ *(Size *)dst = newPix;
+ } else if (overwriteAlpha) {
+ *(Size *)dst = pix | alphaMask;
+ }
+
+ src += sizeof(Size);
+ dst += sizeof(Size);
+ }
+
+ src += srcDelta;
+ dst += dstDelta;
+ }
+}
+
+template<typename Size, bool skipTransparent>
+inline void setAlphaLogic(byte *dst, const byte *src, const uint w, const uint h,
+ const uint srcDelta, const uint dstDelta,
+ const Graphics::PixelFormat &format, const uint8 alpha) {
+
+ const uint32 newAlpha = format.ARGBToColor(alpha, 0, 0, 0);
+ const uint32 rgbMask = format.ARGBToColor(0, 255, 255, 255);
+ const uint32 alphaMask = format.ARGBToColor(255, 0, 0, 0);
+
+ for (uint y = 0; y < h; ++y) {
+ for (uint x = 0; x < w; ++x) {
+ uint32 pix = *(const Size *)src;
+
+ if (!skipTransparent || (pix & alphaMask))
+ *(Size *)dst = (pix & rgbMask) | newAlpha;
+ else
+ *(Size *)dst = pix;
+
+ src += sizeof(Size);
+ dst += sizeof(Size);
+ }
+
+ src += srcDelta;
+ dst += dstDelta;
+ }
+}
+
+} // End of anonymous namespace
+
+// Function to merge a transparent color key with the alpha channel
+bool applyColorKey(byte *dst, const byte *src,
+ const uint dstPitch, const uint srcPitch,
+ const uint w, const uint h,
+ const Graphics::PixelFormat &format, const bool overwriteAlpha,
+ const uint8 rKey, const uint8 gKey, const uint8 bKey,
+ const uint8 rNew, const uint8 gNew, const uint8 bNew) {
+
+ // Faster, but larger, to provide optimized handling for each case.
+ const uint srcDelta = (srcPitch - w * format.bytesPerPixel);
+ const uint dstDelta = (dstPitch - w * format.bytesPerPixel);
+
+ if (format.aBits() == 0) {
+ return false;
+ }
+
+ if (overwriteAlpha) {
+ if (format.bytesPerPixel == 1) {
+ applyColorKeyLogic<uint8, true>(dst, src, w, h, srcDelta, dstDelta, format, rKey, gKey, bKey, rNew, gNew, bNew);
+ } else if (format.bytesPerPixel == 2) {
+ applyColorKeyLogic<uint16, true>(dst, src, w, h, srcDelta, dstDelta, format, rKey, gKey, bKey, rNew, gNew, bNew);
+ } else if (format.bytesPerPixel == 4) {
+ applyColorKeyLogic<uint32, true>(dst, src, w, h, srcDelta, dstDelta, format, rKey, gKey, bKey, rNew, gNew, bNew);
+ } else {
+ return false;
+ }
+ } else {
+ if (format.bytesPerPixel == 1) {
+ applyColorKeyLogic<uint8, false>(dst, src, w, h, srcDelta, dstDelta, format, rKey, gKey, bKey, rNew, gNew, bNew);
+ } else if (format.bytesPerPixel == 2) {
+ applyColorKeyLogic<uint16, false>(dst, src, w, h, srcDelta, dstDelta, format, rKey, gKey, bKey, rNew, gNew, bNew);
+ } else if (format.bytesPerPixel == 4) {
+ applyColorKeyLogic<uint32, false>(dst, src, w, h, srcDelta, dstDelta, format, rKey, gKey, bKey, rNew, gNew, bNew);
+ } else {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Function to set the alpha channel for all pixels to the specified value
+bool setAlpha(byte *dst, const byte *src,
+ const uint dstPitch, const uint srcPitch,
+ const uint w, const uint h,
+ const Graphics::PixelFormat &format,
+ const bool skipTransparent, const uint8 alpha) {
+
+ // Faster, but larger, to provide optimized handling for each case.
+ const uint srcDelta = (srcPitch - w * format.bytesPerPixel);
+ const uint dstDelta = (dstPitch - w * format.bytesPerPixel);
+
+ if (format.aBits() == 0) {
+ return false;
+ }
+
+ if (skipTransparent) {
+ if (format.bytesPerPixel == 1) {
+ setAlphaLogic<uint8, true>(dst, src, w, h, srcDelta, dstDelta, format, alpha);
+ } else if (format.bytesPerPixel == 2) {
+ setAlphaLogic<uint16, true>(dst, src, w, h, srcDelta, dstDelta, format, alpha);
+ } else if (format.bytesPerPixel == 4) {
+ setAlphaLogic<uint32, true>(dst, src, w, h, srcDelta, dstDelta, format, alpha);
+ } else {
+ return false;
+ }
+ } else {
+ if (format.bytesPerPixel == 1) {
+ setAlphaLogic<uint8, false>(dst, src, w, h, srcDelta, dstDelta, format, alpha);
+ } else if (format.bytesPerPixel == 2) {
+ setAlphaLogic<uint16, false>(dst, src, w, h, srcDelta, dstDelta, format, alpha);
+ } else if (format.bytesPerPixel == 4) {
+ setAlphaLogic<uint32, false>(dst, src, w, h, srcDelta, dstDelta, format, alpha);
+ } else {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+} // End of namespace Graphics
diff --git a/graphics/blit.h b/graphics/blit.h
index aae83aafa0b..395cefbeac7 100644
--- a/graphics/blit.h
+++ b/graphics/blit.h
@@ -176,6 +176,20 @@ bool rotoscaleBlitBilinear(byte *dst, const byte *src,
const Graphics::PixelFormat &fmt,
const TransformStruct &transform,
const Common::Point &newHotspot);
+
+bool applyColorKey(byte *dst, const byte *src,
+ const uint dstPitch, const uint srcPitch,
+ const uint w, const uint h,
+ const Graphics::PixelFormat &format, const bool overwriteAlpha,
+ const uint8 rKey, const uint8 gKey, const uint8 bKey,
+ const uint8 rNew, const uint8 gNew, const uint8 bNew);
+
+bool setAlpha(byte *dst, const byte *src,
+ const uint dstPitch, const uint srcPitch,
+ const uint w, const uint h,
+ const Graphics::PixelFormat &format,
+ const bool skipTransparent, const uint8 alpha);
+
/** @} */
} // End of namespace Graphics
diff --git a/graphics/module.mk b/graphics/module.mk
index 3c8071559a7..196be8a5265 100644
--- a/graphics/module.mk
+++ b/graphics/module.mk
@@ -3,6 +3,7 @@ MODULE := graphics
MODULE_OBJS := \
big5.o \
blit.o \
+ blit-alpha.o \
blit-scale.o \
cursorman.o \
font.o \
diff --git a/graphics/surface.cpp b/graphics/surface.cpp
index 5e9b656dbf6..e3107c132a4 100644
--- a/graphics/surface.cpp
+++ b/graphics/surface.cpp
@@ -426,6 +426,22 @@ void Surface::flipHorizontal(const Common::Rect &r) {
}
}
+bool Surface::applyColorKey(uint8 rKey, uint8 gKey, uint8 bKey, bool overwriteAlpha) {
+ return Graphics::applyColorKey((byte *)pixels, (const byte *)pixels, pitch, pitch, w, h, format,
+ overwriteAlpha, rKey, gKey, bKey, rKey, gKey, bKey);
+}
+
+bool Surface::applyColorKey(uint8 rKey, uint8 gKey, uint8 bKey, bool overwriteAlpha,
+ uint8 rNew, uint8 gNew, uint8 bNew) {
+ return Graphics::applyColorKey((byte *)pixels, (const byte *)pixels, pitch, pitch, w, h, format,
+ overwriteAlpha, rKey, gKey, bKey, rNew, gNew, bNew);
+}
+
+bool Surface::setAlpha(uint8 alpha, bool skipTransparent) {
+ return Graphics::setAlpha((byte *)pixels, (const byte *)pixels, pitch, pitch, w, h, format,
+ skipTransparent, alpha);
+}
+
Graphics::Surface *Surface::scale(int16 newWidth, int16 newHeight, bool filtering) const {
Graphics::Surface *target = new Graphics::Surface();
diff --git a/graphics/surface.h b/graphics/surface.h
index 857e1768e64..7ab9090c169 100644
--- a/graphics/surface.h
+++ b/graphics/surface.h
@@ -465,6 +465,35 @@ public:
*/
void flipHorizontal(const Common::Rect &r);
+ /**
+ * Writes a color key to the alpha channel of the surface
+ * @param rKey the red component of the color key
+ * @param gKey the green component of the color key
+ * @param bKey the blue component of the color key
+ * @param overwriteAlpha if true, all other alpha will be set fully opaque
+ */
+ bool applyColorKey(uint8 rKey, uint8 gKey, uint8 bKey, bool overwriteAlpha = false);
+
+ /**
+ * Writes a color key to the alpha channel of the surface
+ * @param rKey the red component of the color key
+ * @param gKey the green component of the color key
+ * @param bKey the blue component of the color key
+ * @param overwriteAlpha if true, all other alpha will be set fully opaque
+ * @param rNew the red component to replace the color key with
+ * @param gNew the green component to replace the color key with
+ * @param bNew the blue component to replace the color key with
+ */
+ bool applyColorKey(uint8 rKey, uint8 gKey, uint8 bKey, bool overwriteAlpha,
+ uint8 rNew, uint8 gNew, uint8 bNew);
+
+ /**
+ * Sets alpha channel for all pixels to specified value
+ * @param alpha value of the alpha channel to set
+ * @param skipTransparent if set to true, then do not touch pixels with alpha=0
+ */
+ bool setAlpha(uint8 alpha, bool skipTransparent = false);
+
/**
* Scale the data to the given size.
*
diff --git a/graphics/transparent_surface.cpp b/graphics/transparent_surface.cpp
index ef4c3292163..66a1ed61652 100644
--- a/graphics/transparent_surface.cpp
+++ b/graphics/transparent_surface.cpp
@@ -682,50 +682,6 @@ Common::Rect TransparentSurface::blitClip(Graphics::Surface &target, Common::Rec
return retSize;
}
-/**
- * Writes a color key to the alpha channel of the surface
- * @param rKey the red component of the color key
- * @param gKey the green component of the color key
- * @param bKey the blue component of the color key
- * @param overwriteAlpha if true, all other alpha will be set fully opaque
- */
-void TransparentSurface::applyColorKey(uint8 rKey, uint8 gKey, uint8 bKey, bool overwriteAlpha) {
- assert(format.bytesPerPixel == 4);
- for (int i = 0; i < h; i++) {
- for (int j = 0; j < w; j++) {
- uint32 pix = ((uint32 *)pixels)[i * w + j];
- uint8 r, g, b, a;
- format.colorToARGB(pix, a, r, g, b);
- if (r == rKey && g == gKey && b == bKey) {
- a = 0;
- ((uint32 *)pixels)[i * w + j] = format.ARGBToColor(a, r, g, b);
- } else if (overwriteAlpha) {
- a = 255;
- ((uint32 *)pixels)[i * w + j] = format.ARGBToColor(a, r, g, b);
- }
- }
- }
-}
-
-/**
- * Sets alpha channel for all pixels to specified value
- * @param alpha value of the alpha channel to set
- * @param skipTransparent if set to true, then do not touch pixels with alpha=0
- */
-void TransparentSurface::setAlpha(uint8 alpha, bool skipTransparent) {
- assert(format.bytesPerPixel == 4);
- for (int i = 0; i < h; i++) {
- for (int j = 0; j < w; j++) {
- uint32 pix = ((uint32 *)pixels)[i * w + j];
- uint8 r, g, b, a;
- format.colorToARGB(pix, a, r, g, b);
- if (!skipTransparent || a)
- a = alpha;
- ((uint32 *)pixels)[i * w + j] = format.ARGBToColor(a, r, g, b);
- }
- }
-}
-
AlphaType TransparentSurface::getAlphaMode() const {
return _alphaMode;
}
diff --git a/graphics/transparent_surface.h b/graphics/transparent_surface.h
index 5e6b292ead8..9a4f7d644b6 100644
--- a/graphics/transparent_surface.h
+++ b/graphics/transparent_surface.h
@@ -115,9 +115,6 @@ struct TransparentSurface : public Graphics::Surface {
int width = -1, int height = -1,
TSpriteBlendMode blend = BLEND_NORMAL);
- void applyColorKey(uint8 r, uint8 g, uint8 b, bool overwriteAlpha = false);
- void setAlpha(uint8 alpha, bool skipTransparent = false);
-
/**
* @brief Scale function; this returns a transformed version of this surface after rotation and
* scaling. Please do not use this if angle != 0, use rotoscale.
More information about the Scummvm-git-logs
mailing list