[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