|
| 1 | +import 'dart:math'; |
| 2 | +import 'dart:ui' as ui; |
| 3 | + |
| 4 | +import 'package:flutter_test_goldens/src/goldens/pixel_comparisons.dart'; |
| 5 | +import 'package:image/image.dart'; |
| 6 | + |
| 7 | +import 'package:flutter_test_goldens/flutter_test_goldens.dart'; |
| 8 | + |
| 9 | +/// Given a [mismatch] between a golden and a screenshot, generates an image |
| 10 | +/// that shows the golden, the screenshot, and the differences between them. |
| 11 | +Future<Image> paintGoldenMismatchImages(GoldenMismatch mismatch) async { |
| 12 | + final goldenWidth = mismatch.golden!.image.width; |
| 13 | + final goldenHeight = mismatch.golden!.image.height; |
| 14 | + |
| 15 | + final screenshotWidth = mismatch.screenshot!.image.width; |
| 16 | + final screenshotHeight = mismatch.screenshot!.image.height; |
| 17 | + |
| 18 | + final maxWidth = max(goldenWidth, screenshotWidth); |
| 19 | + final maxHeight = max(goldenHeight, screenshotHeight); |
| 20 | + |
| 21 | + final failureImage = Image( |
| 22 | + width: maxWidth * 2, |
| 23 | + height: maxHeight * 2, |
| 24 | + ); |
| 25 | + |
| 26 | + // Copy golden to top left corner. |
| 27 | + for (int x = 0; x < goldenWidth; x += 1) { |
| 28 | + for (int y = 0; y < goldenHeight; y += 1) { |
| 29 | + final goldenPixel = mismatch.golden!.image.getPixel(x, y); |
| 30 | + failureImage.setPixel(x, y, goldenPixel); |
| 31 | + } |
| 32 | + } |
| 33 | + |
| 34 | + // Copy screenshot to top right corner. |
| 35 | + for (int x = 0; x < screenshotWidth; x += 1) { |
| 36 | + for (int y = 0; y < screenshotHeight; y += 1) { |
| 37 | + final screenshotPixel = mismatch.screenshot!.image.getPixel(x, y); |
| 38 | + failureImage.setPixel(maxWidth + x, y, screenshotPixel); |
| 39 | + } |
| 40 | + } |
| 41 | + |
| 42 | + // Paint mismatch images. |
| 43 | + final absoluteDiffColor = ColorUint32.rgb(255, 255, 0); |
| 44 | + for (int x = 0; x < maxWidth; x += 1) { |
| 45 | + for (int y = 0; y < maxHeight; y += 1) { |
| 46 | + if (x >= goldenWidth || x >= screenshotWidth || y >= goldenHeight || y >= screenshotHeight) { |
| 47 | + // This pixel doesn't exist in the golden, or it doesn't exist in the |
| 48 | + // screenshot. Therefore, we have nothing to compare. Treat this pixel |
| 49 | + // as a max severity difference. |
| 50 | + |
| 51 | + // Paint this pixel in the absolute diff image. |
| 52 | + failureImage.setPixel(x, maxHeight + y, absoluteDiffColor); |
| 53 | + |
| 54 | + // Paint this pixel in the relative severity diff image. |
| 55 | + failureImage.setPixel(maxWidth + x, maxHeight + y, absoluteDiffColor); |
| 56 | + |
| 57 | + continue; |
| 58 | + } |
| 59 | + |
| 60 | + // Check if the screenshot matches the golden. |
| 61 | + final goldenPixel = mismatch.golden!.image.getPixel(x, y); |
| 62 | + final screenshotPixel = mismatch.screenshot!.image.getPixel(x, y); |
| 63 | + final pixelsMatch = goldenPixel == screenshotPixel; |
| 64 | + if (pixelsMatch) { |
| 65 | + continue; |
| 66 | + } |
| 67 | + |
| 68 | + // Paint this pixel in the absolute diff image. |
| 69 | + failureImage.setPixel(x, maxHeight + y, absoluteDiffColor); |
| 70 | + |
| 71 | + // Paint this pixel in the relative severity diff image. |
| 72 | + final mismatchPercent = calculateColorMismatchPercent(goldenPixel, screenshotPixel); |
| 73 | + final yellowAmount = ui.lerpDouble(0.2, 1.0, mismatchPercent)!; |
| 74 | + failureImage.setPixel( |
| 75 | + goldenWidth + x, |
| 76 | + goldenHeight + y, |
| 77 | + ColorUint32.rgb((255 * yellowAmount).round(), (255 * yellowAmount).round(), 0), |
| 78 | + ); |
| 79 | + } |
| 80 | + } |
| 81 | + |
| 82 | + return failureImage; |
| 83 | +} |
0 commit comments