[Scummvm-git-logs] scummvm master -> a7a41273cf514200c312345d635a2419cd57ae52

sev- noreply at scummvm.org
Wed Jul 26 21:37:41 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:
a7a41273cf DIRECTOR: Improve screenshot comparison of previous builds


Commit: a7a41273cf514200c312345d635a2419cd57ae52
    https://github.com/scummvm/scummvm/commit/a7a41273cf514200c312345d635a2419cd57ae52
Author: Harishankar Kumar (hari01584 at gmail.com)
Date: 2023-07-26T23:37:37+02:00

Commit Message:
DIRECTOR: Improve screenshot comparison of previous builds

This patch adds simple pixel by pixel comparison of screenshots
between builds. It is useful to detect regressions in graphics
rendering.

Changed paths:
    engines/director/score.cpp
    engines/director/score.h
    engines/director/types.h


diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 23f73cc59ea..e0aba399c62 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -24,6 +24,7 @@
 #include "common/config-manager.h"
 #include "common/file.h"
 #include "common/md5.h"
+#include "common/rational.h"
 #include "common/memstream.h"
 #include "common/punycode.h"
 #include "common/substream.h"
@@ -1138,10 +1139,51 @@ void Score::invalidateRectsForMember(CastMember *member) {
 	}
 }
 
-static Common::String computeSurfaceMd5(const Graphics::Surface *surf) {
-	Common::MemoryReadStream stream((const byte *)surf->getPixels(), surf->pitch * surf->h);
+bool Score::checkShotSimilarity(const Graphics::Surface *oldSurface, const Graphics::Surface *newSurface) {
+	if (oldSurface->w != newSurface->w || oldSurface->h != newSurface->h || oldSurface->format != newSurface->format) {
+		warning("BUILDBOT: Score::checkShotSimilarity(): Dimensions or format do not match");
+		return false;
+	}
+
+	uint32 absolute_pixel_differences = 0;
+	uint32 different_pixel_count = 0;
+	uint32 total_pixel_count = oldSurface->w * oldSurface->h;
+
+	for (int y = 0; y < oldSurface->h; y++) {
+		const uint32 *oldPtr = (const uint32 *)oldSurface->getBasePtr(0, y);
+		const uint32 *newPtr = (const uint32 *)newSurface->getBasePtr(0, y);
+
+		for (int x = 0; x < oldSurface->w; x++) {
+			uint32 newColor = *newPtr++;
+      		uint32 oldColor = *oldPtr++;
+
+			if (newColor != oldColor) {
+				absolute_pixel_differences++;
+
+				for (int c = 0; c < 4; c++) {
+					if (ABS((newColor & 0xFF) - (oldColor & 0xFF)) > kShotColorDiffThreshold) {
+						different_pixel_count++;
+						break;
+					}
+
+					newColor >>= 8;
+					oldColor >>= 8;
+				}
+			}
+		}
+	}
+
+	// Check 1: If two images are absolutely same, we don't need to check further
+	if (absolute_pixel_differences == 0) {
+		return true;
+	}
+
+	// Check 2: Images are different, but the difference can be small enough to be in threshold
+	Common::Rational difference_percentage = Common::Rational(different_pixel_count, total_pixel_count);
+	if (difference_percentage > kShotPercentPixelThreshold)
+		warning("BUILDBOT: Score::checkShotSimilarity(): Screenshot is %d%% different from previous one, threshold is %d percent", difference_percentage.getNumerator() * 100 / difference_percentage.getDenominator(), kShotPercentPixelThreshold);
 
-	return Common::computeStreamMD5AsString(stream);
+	return false;
 }
 
 void Score::screenShot() {
@@ -1201,15 +1243,11 @@ void Score::screenShot() {
 			Common::SeekableReadStream *stream = fs.createReadStream();
 
 			if (stream && decoder.loadStream(*stream)) {
-				Common::String oldMd5 = computeSurfaceMd5(decoder.getSurface());
-				Common::String newMd5 = computeSurfaceMd5(newSurface);
-
-				if (oldMd5 == newMd5) {
+				if (checkShotSimilarity(decoder.getSurface(), newSurface)) {
 					warning("Screenshot is equal to previous one, skipping: %s", filename.c_str());
 					newSurface->free();
 					delete newSurface;
 					delete stream;
-
 					return;
 				}
 			} else {
diff --git a/engines/director/score.h b/engines/director/score.h
index eed0a54f49b..3cee4eeed98 100644
--- a/engines/director/score.h
+++ b/engines/director/score.h
@@ -145,6 +145,7 @@ private:
 	void playQueuedSound();
 
 	void screenShot();
+	bool checkShotSimilarity(const Graphics::Surface *surface1, const Graphics::Surface *surface2);
 
 	bool processImmediateFrameScript(Common::String s, int id);
 	bool processFrozenScripts();
diff --git a/engines/director/types.h b/engines/director/types.h
index ee8557482d3..cd170807e1f 100644
--- a/engines/director/types.h
+++ b/engines/director/types.h
@@ -32,6 +32,11 @@ enum {
 	kFewFamesMaxCounter = 19,
 };
 
+enum {
+	kShotColorDiffThreshold = 2,
+	kShotPercentPixelThreshold = 1
+};
+
 #define kQuirksCacheArchive "quirks"
 
 enum MovieFlag {




More information about the Scummvm-git-logs mailing list