@@ -87,6 +87,52 @@ export function visualSuite(
87
87
} ) ;
88
88
}
89
89
90
+ /**
91
+ * Image Diff Algorithm for p5.js Visual Tests
92
+ *
93
+ * This algorithm addresses the challenge of cross-platform rendering differences in p5.js visual tests.
94
+ * Different operating systems and browsers render graphics with subtle variations, particularly with
95
+ * anti-aliasing, text rendering, and sub-pixel positioning. This can cause false negatives in tests
96
+ * when the visual differences are acceptable rendering variations rather than actual bugs.
97
+ *
98
+ * Key components of the approach:
99
+ *
100
+ * 1. Initial pixel-by-pixel comparison:
101
+ * - Uses pixelmatch to identify differences between expected and actual images
102
+ * - Sets a moderate threshold (0.5) to filter out minor color/intensity variations
103
+ * - Produces a diff image with red pixels marking differences
104
+ *
105
+ * 2. Cluster identification using BFS (Breadth-First Search):
106
+ * - Groups connected difference pixels into clusters
107
+ * - Uses a queue-based BFS algorithm to find all connected pixels
108
+ * - Defines connectivity based on 8-way adjacency (all surrounding pixels)
109
+ *
110
+ * 3. Cluster categorization by type:
111
+ * - Analyzes each pixel's neighborhood characteristics
112
+ * - Specifically identifies "line shift" clusters - differences that likely represent
113
+ * the same visual elements shifted by 1px due to platform rendering differences
114
+ * - Line shifts are identified when >80% of pixels in a cluster have ≤2 neighboring diff pixels
115
+ *
116
+ * 4. Intelligent failure criteria:
117
+ * - Filters out clusters smaller than MIN_CLUSTER_SIZE pixels (noise reduction)
118
+ * - Applies different thresholds for regular differences vs. line shifts
119
+ * - Considers both the total number of significant pixels and number of distinct clusters
120
+ *
121
+ * This approach balances the need to catch genuine visual bugs (like changes to shape geometry,
122
+ * colors, or positioning) while tolerating acceptable cross-platform rendering variations.
123
+ *
124
+ * Parameters:
125
+ * - MIN_CLUSTER_SIZE: Minimum size for a cluster to be considered significant (default: 4)
126
+ * - MAX_TOTAL_DIFF_PIXELS: Maximum allowed non-line-shift difference pixels (default: 40)
127
+ * Note: These can be adjusted for further updation
128
+ *
129
+ * Note for contributors: When running tests locally, you may not see these differences as they
130
+ * mainly appear when tests run on different operating systems or browser rendering engines.
131
+ * However, the same code may produce slightly different renderings on CI environments, particularly
132
+ * with text positioning, thin lines, or curved shapes. This algorithm helps distinguish between
133
+ * these acceptable variations and actual visual bugs.
134
+ */
135
+
90
136
export async function checkMatch ( actual , expected , p5 ) {
91
137
let scale = Math . min ( MAX_SIDE / expected . width , MAX_SIDE / expected . height ) ;
92
138
const ratio = expected . width / expected . height ;
@@ -174,15 +220,12 @@ export async function checkMatch(actual, expected, p5) {
174
220
// Define significance thresholds
175
221
const MIN_CLUSTER_SIZE = 4 ; // Minimum pixels in a significant cluster
176
222
const MAX_TOTAL_DIFF_PIXELS = 40 ; // Maximum total different pixels
177
- const MAX_LINE_SHIFT_PIXELS = 200 ;
178
223
179
224
// Determine if the differences are significant
180
- const lineShiftClusters = clusterSizes . filter ( c => c . isLineShift && c . size > MIN_CLUSTER_SIZE ) ;
181
225
const nonLineShiftClusters = clusterSizes . filter ( c => ! c . isLineShift && c . size >= MIN_CLUSTER_SIZE ) ;
182
226
183
227
// Calculate significant differences excluding line shifts
184
228
const significantDiffPixels = nonLineShiftClusters . reduce ( ( sum , c ) => sum + c . size , 0 ) ;
185
- const lineShiftPixels = lineShiftClusters . reduce ( ( sum , c ) => sum + c . size , 0 ) ;
186
229
187
230
// Update the diff canvas
188
231
diffCanvas . updatePixels ( ) ;
0 commit comments