3
3
using System . Globalization ;
4
4
using System . IO ;
5
5
using System . Linq ;
6
+ using System . Numerics ;
6
7
using System . Security . Cryptography ;
7
8
using System . Text ;
8
9
using System . Threading . Tasks ;
@@ -24,10 +25,10 @@ internal CompareResult Compare(string[] artifacts)
24
25
{
25
26
var testResult = new CompareResult ( _platform ) ;
26
27
27
- string path = _basePath ;
28
+ var path = _basePath ;
28
29
var resultsId = $ "{ DateTime . Now : yyyyMMdd-hhmmss} ";
29
- string diffPath = Path . Combine ( _basePath , $ "Results-{ _platform } -{ resultsId } ") ;
30
- string resultsFilePath = Path . Combine ( _basePath , $ "Results-{ _platform } -{ resultsId } .html") ;
30
+ var diffPath = Path . Combine ( _basePath , $ "Results-{ _platform } -{ resultsId } ") ;
31
+ var resultsFilePath = Path . Combine ( _basePath , $ "Results-{ _platform } -{ resultsId } .html") ;
31
32
32
33
Directory . CreateDirectory ( path ) ;
33
34
Directory . CreateDirectory ( diffPath ) ;
@@ -97,7 +98,7 @@ select testFileIncrements
97
98
return a ;
98
99
}
99
100
100
- var otherMatch = a . Reverse ( ) . Where ( i => i . IdSha != null ) . FirstOrDefault ( ) ;
101
+ var otherMatch = a . Reverse ( ) . FirstOrDefault ( i => i . IdSha != null ) ;
101
102
if ( platformFiles . FileInfo ? . Id . sha != otherMatch ? . IdSha )
102
103
{
103
104
return a
@@ -114,7 +115,7 @@ select testFileIncrements
114
115
)
115
116
) . ToArray ( ) ;
116
117
117
- var hasChanges = increments . Any ( i => i . Where ( v => v . IdSha != null ) . Count ( ) - 1 > 1 ) ;
118
+ var hasChanges = increments . Any ( i => i . Count ( v => v . IdSha != null ) - 1 > 1 ) ;
118
119
119
120
var compareResultFile = new CompareResultFile ( ) ;
120
121
compareResultFile . HasChanged = hasChanges ;
@@ -126,13 +127,13 @@ select testFileIncrements
126
127
127
128
var firstFolder = changeResult . Where ( i => i . FolderIndex != - 1 ) . Min ( i => i . FolderIndex ) ;
128
129
129
- for ( int folderIndex = 0 ; folderIndex < allFolders . Length ; folderIndex ++ )
130
+ for ( var folderIndex = 0 ; folderIndex < allFolders . Length ; folderIndex ++ )
130
131
{
131
132
var folderInfo = changeResult . FirstOrDefault ( inc => inc . FolderIndex == folderIndex ) ;
132
133
133
134
if ( folderInfo != null )
134
135
{
135
- var hasChangedFromPrevious = folderIndex != firstFolder && folderInfo ? . IdSha != null ;
136
+ var hasChangedFromPrevious = folderIndex != firstFolder && folderInfo . IdSha != null ;
136
137
137
138
var compareResultFileRun = new CompareResultFileRun ( ) ;
138
139
compareResultFile . ResultRun . Add ( compareResultFileRun ) ;
@@ -144,37 +145,34 @@ select testFileIncrements
144
145
145
146
compareResultFileRun . HasChanged = hasChangedFromPrevious ;
146
147
147
- if ( folderInfo != null )
148
+ var previousFolderInfo = changeResult . FirstOrDefault ( inc => inc . FolderIndex == folderIndex - 1 ) ;
149
+ if ( hasChangedFromPrevious && previousFolderInfo != null )
148
150
{
149
- var previousFolderInfo = changeResult . FirstOrDefault ( inc => inc . FolderIndex == folderIndex - 1 ) ;
150
- if ( hasChangedFromPrevious && previousFolderInfo != null )
151
+ try
151
152
{
152
- try
153
- {
154
- var currentImage = DecodeImage ( folderInfo . Path ) ;
155
- var previousImage = DecodeImage ( previousFolderInfo . Path ) ;
156
-
157
- if ( currentImage . pixels . Length == previousImage . pixels . Length )
158
- {
159
- var diff = DiffImages ( currentImage . pixels , previousImage . pixels , currentImage . frame . Format . BitsPerPixel / 8 ) ;
153
+ var currentImage = DecodeImage ( folderInfo . Path ) ;
154
+ var previousImage = DecodeImage ( previousFolderInfo . Path ) ;
160
155
161
- var diffFilePath = Path . Combine ( diffPath , $ "{ folderInfo . Id } -{ folderInfo . CompareeId } .png") ;
162
- WriteImage ( diffFilePath , diff , currentImage . frame , currentImage . stride ) ;
156
+ if ( currentImage . pixels . Length == previousImage . pixels . Length )
157
+ {
158
+ var diff = DiffImages ( currentImage . pixels , previousImage . pixels , currentImage . frame . Format . BitsPerPixel / 8 ) ;
163
159
164
- compareResultFileRun . DiffResultImage = diffFilePath ;
165
- }
160
+ var diffFilePath = Path . Combine ( diffPath , $ " { folderInfo . Id } - { folderInfo . CompareeId } .png" ) ;
161
+ WriteImage ( diffFilePath , diff , currentImage . frame , currentImage . stride ) ;
166
162
167
- changedList . Add ( testFile ) ;
163
+ compareResultFileRun . DiffResultImage = diffFilePath ;
168
164
}
169
- catch ( Exception ex )
170
- {
171
- Helpers . WriteLineWithTime ( $ "[ERROR] Failed to process [{ folderInfo . Path } ] and [{ previousFolderInfo . Path } ]\n ({ ex } )") ;
172
- }
173
- }
174
165
175
- GC . Collect ( 2 , GCCollectionMode . Forced ) ;
176
- GC . WaitForPendingFinalizers ( ) ;
166
+ changedList . Add ( testFile ) ;
167
+ }
168
+ catch ( Exception ex )
169
+ {
170
+ Helpers . WriteLineWithTime ( $ "[ERROR] Failed to process [{ folderInfo . Path } ] and [{ previousFolderInfo . Path } ]\n ({ ex } )") ;
171
+ }
177
172
}
173
+
174
+ GC . Collect ( 2 , GCCollectionMode . Forced ) ;
175
+ GC . WaitForPendingFinalizers ( ) ;
178
176
}
179
177
}
180
178
}
@@ -187,7 +185,7 @@ select testFileIncrements
187
185
188
186
private bool CanBeUsedForCompare ( string sample )
189
187
{
190
- if ( ReadScreenshotMetadata ( sample ) is IDictionary < string , string > options )
188
+ if ( ReadScreenshotMetadata ( sample ) is { } options )
191
189
{
192
190
if ( options . TryGetValue ( "IgnoreInSnapshotCompare" , out var ignore ) && ignore . Equals ( "true" , StringComparison . OrdinalIgnoreCase ) )
193
191
{
@@ -200,7 +198,8 @@ private bool CanBeUsedForCompare(string sample)
200
198
201
199
private static IDictionary < string , string > ReadScreenshotMetadata ( string sample )
202
200
{
203
- var metadataFile = Path . Combine ( Path . GetDirectoryName ( sample ) , Path . GetFileNameWithoutExtension ( sample ) + ".metadata" ) ;
201
+ var metadataFile = Path . Combine ( Path . GetDirectoryName ( sample ) ,
202
+ $ "{ Path . GetFileNameWithoutExtension ( sample ) } .metadata") ;
204
203
205
204
if ( File . Exists ( metadataFile ) )
206
205
{
@@ -222,7 +221,7 @@ private static IDictionary<string, string> ReadScreenshotMetadata(string sample)
222
221
{
223
222
using ( var sha1 = SHA1 . Create ( ) )
224
223
{
225
- using ( var file = File . OpenRead ( @"\\?\" + sample ) )
224
+ using ( var file = File . OpenRead ( $ @ "\\?\{ sample } " ) )
226
225
{
227
226
var data = sha1 . ComputeHash ( file ) ;
228
227
@@ -232,7 +231,7 @@ private static IDictionary<string, string> ReadScreenshotMetadata(string sample)
232
231
233
232
// Loop through each byte of the hashed data
234
233
// and format each one as a hexadecimal string.
235
- for ( int i = 0 ; i < data . Length ; i ++ )
234
+ for ( var i = 0 ; i < data . Length ; i ++ )
236
235
{
237
236
sBuilder . Append ( data [ i ] . ToString ( "x2" , CultureInfo . InvariantCulture ) ) ;
238
237
}
@@ -261,7 +260,7 @@ private IEnumerable<string> EnumerateFiles(string path, string pattern)
261
260
}
262
261
else
263
262
{
264
- return new string [ 0 ] ;
263
+ return [ ] ;
265
264
}
266
265
}
267
266
@@ -289,30 +288,45 @@ private void WriteImage(string diffPath, byte[] diff, BitmapFrame frameInfo, int
289
288
}
290
289
}
291
290
292
- private byte [ ] DiffImages ( byte [ ] currentImage , byte [ ] previousImage , int pixelSize )
291
+ private byte [ ] DiffImages ( ReadOnlySpan < byte > currentImage , ReadOnlySpan < byte > previousImage , int pixelSize )
293
292
{
294
- for ( int i = 0 ; i < currentImage . Length ; i ++ )
293
+ var length = currentImage . Length ;
294
+ var resultImage = new byte [ length ] ;
295
+ var vectorSize = Vector < byte > . Count ;
296
+ var i = 0 ;
297
+
298
+ // Apply XOR with SIMD on blocks of size 'vectorSize'
299
+ for ( ; i <= length - vectorSize ; i += vectorSize )
295
300
{
296
- currentImage [ i ] = ( byte ) ( currentImage [ i ] ^ previousImage [ i ] ) ;
301
+ var currentVector = new Vector < byte > ( currentImage . Slice ( i , vectorSize ) ) ;
302
+ var previousVector = new Vector < byte > ( previousImage . Slice ( i , vectorSize ) ) ;
303
+ var resultVector = currentVector ^ previousVector ;
304
+ resultVector . CopyTo ( resultImage . AsSpan ( i , vectorSize ) ) ;
297
305
}
298
306
307
+ // Process remaining pixels without SIMD if necessary
308
+ for ( ; i < length ; i ++ )
309
+ {
310
+ resultImage [ i ] = ( byte ) ( currentImage [ i ] ^ previousImage [ i ] ) ;
311
+ }
312
+
313
+ // If pixelSize is 4, force opacity on every fourth byte
299
314
if ( pixelSize == 4 )
300
315
{
301
- // Force result to be opaque
302
- for ( int i = 0 ; i < currentImage . Length ; i += 4 )
316
+ for ( i = 3 ; i < length ; i += 4 )
303
317
{
304
- currentImage [ i + 3 ] = 0xFF ;
318
+ resultImage [ i ] = 0xFF ;
305
319
}
306
320
}
307
321
308
- return currentImage ;
322
+ return resultImage ;
309
323
}
310
324
311
325
private ( BitmapFrame frame , byte [ ] pixels , int stride ) DecodeImage ( string path1 )
312
326
{
313
327
try
314
328
{
315
- using ( Stream imageStreamSource = new FileStream ( @"\\?\" + path1 , FileMode . Open , FileAccess . Read , FileShare . Read ) )
329
+ using ( Stream imageStreamSource = new FileStream ( $ @ "\\?\{ path1 } " , FileMode . Open , FileAccess . Read , FileShare . Read ) )
316
330
{
317
331
var decoder = new PngBitmapDecoder ( imageStreamSource , BitmapCreateOptions . PreservePixelFormat , BitmapCacheOption . Default ) ;
318
332
@@ -322,9 +336,9 @@ private byte[] DiffImages(byte[] currentImage, byte[] previousImage, int pixelSi
322
336
sourceStride += ( 4 - sourceStride % 4 ) ;
323
337
324
338
var image = new byte [ sourceStride * ( f . PixelHeight * sourceBytesPerPixels ) ] ;
325
- decoder . Frames [ 0 ] . CopyPixels ( image , ( int ) sourceStride , 0 ) ;
339
+ f . CopyPixels ( image , ( int ) sourceStride , 0 ) ;
326
340
327
- return ( decoder . Frames [ 0 ] , image , sourceStride ) ;
341
+ return ( f , image , sourceStride ) ;
328
342
}
329
343
}
330
344
catch ( Exception ex )
@@ -341,6 +355,5 @@ private static IEnumerable<T> LogForeach<T>(IEnumerable<T> q, Action<T> action)
341
355
yield return item ;
342
356
}
343
357
}
344
-
345
358
}
346
359
}
0 commit comments