|
23 | 23 |
|
24 | 24 | package jdk.jpackage.test; |
25 | 25 |
|
| 26 | +import java.awt.image.BufferedImage; |
26 | 27 | import java.io.IOException; |
27 | 28 | import java.lang.reflect.InvocationTargetException; |
28 | 29 | import java.lang.reflect.Method; |
29 | 30 | import java.nio.file.Files; |
30 | 31 | import java.nio.file.Path; |
31 | 32 | import java.util.Optional; |
| 33 | +import javax.imageio.ImageIO; |
32 | 34 |
|
33 | 35 | public final class LauncherIconVerifier { |
34 | 36 | public LauncherIconVerifier() { |
@@ -99,13 +101,56 @@ void verifyLauncherIcon(JPackageCommand cmd, String launcherName, |
99 | 101 | iconWorkDir, iconContainer, "expected"); |
100 | 102 | Path extractedActualIcon = extractIconFromExecutable(iconWorkDir, |
101 | 103 | launcher, "actual"); |
102 | | - TKit.assertTrue(-1 == Files.mismatch(extractedExpectedIcon, |
103 | | - extractedActualIcon), |
104 | | - String.format( |
105 | | - "Check icon file [%s] of %s launcher is a copy of source icon file [%s]", |
106 | | - extractedActualIcon, |
107 | | - Optional.ofNullable(launcherName).orElse("main"), |
108 | | - extractedExpectedIcon)); |
| 104 | + |
| 105 | + TKit.trace(String.format( |
| 106 | + "Check icon file [%s] of %s launcher is a copy of source icon file [%s]", |
| 107 | + extractedActualIcon, |
| 108 | + Optional.ofNullable(launcherName).orElse("main"), |
| 109 | + extractedExpectedIcon)); |
| 110 | + |
| 111 | + if (Files.mismatch(extractedExpectedIcon, extractedActualIcon) |
| 112 | + != -1) { |
| 113 | + // On Windows11 .NET API extracting icons from executables |
| 114 | + // produce slightly different output for the same icon. |
| 115 | + // To workaround it, compare pixels of images and if the |
| 116 | + // number of off pixels is below a threshold, assume |
| 117 | + // equality. |
| 118 | + BufferedImage expectedImg = ImageIO.read( |
| 119 | + extractedExpectedIcon.toFile()); |
| 120 | + BufferedImage actualImg = ImageIO.read( |
| 121 | + extractedActualIcon.toFile()); |
| 122 | + |
| 123 | + int w = expectedImg.getWidth(); |
| 124 | + int h = expectedImg.getHeight(); |
| 125 | + |
| 126 | + TKit.assertEquals(w, actualImg.getWidth(), |
| 127 | + "Check expected and actual icons have the same width"); |
| 128 | + TKit.assertEquals(h, actualImg.getHeight(), |
| 129 | + "Check expected and actual icons have the same height"); |
| 130 | + |
| 131 | + int diffPixelCount = 0; |
| 132 | + |
| 133 | + for (int i = 0; i != w; ++i) { |
| 134 | + for (int j = 0; j != h; ++j) { |
| 135 | + int expectedRGB = expectedImg.getRGB(i, j); |
| 136 | + int actualRGB = actualImg.getRGB(i, j); |
| 137 | + |
| 138 | + if (expectedRGB != actualRGB) { |
| 139 | + TKit.trace(String.format( |
| 140 | + "Images mismatch at [%d, %d] pixel", i, |
| 141 | + j)); |
| 142 | + diffPixelCount++; |
| 143 | + } |
| 144 | + } |
| 145 | + } |
| 146 | + |
| 147 | + double threshold = 0.1; |
| 148 | + TKit.assertTrue(((double) diffPixelCount) / (w * h) |
| 149 | + < threshold, |
| 150 | + String.format( |
| 151 | + "Check the number of mismatched pixels [%d] of [%d] is < [%f] threshold", |
| 152 | + diffPixelCount, (w * h), threshold)); |
| 153 | + } |
109 | 154 | }); |
110 | 155 | } |
111 | 156 |
|
|
0 commit comments