Skip to content

Commit 26af42e

Browse files
committed
Rework grayscale and resizing ImageFunctions for ImageComparator
Fix documentation for IVisualStateProvider Fix coding issues
1 parent 30938e9 commit 26af42e

File tree

4 files changed

+78
-20
lines changed

4 files changed

+78
-20
lines changed

src/main/java/aquality/selenium/core/visualization/IVisualStateProvider.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ public interface IVisualStateProvider {
3030
* Gets the difference between the image of the element and the provided image using {@link IImageComparator}.
3131
* @param theOtherOne the image to compare the element with.
3232
* @param threshold how big a difference will be ignored as a percentage - value between 0 and 1.
33-
* If the value is null, the default value is got from {@link aquality.selenium.core.configurations.IVisualConfiguration}.
3433
* @return the difference between the two images as a percentage - value between 0 and 1.
3534
*/
3635
float getDifference(Image theOtherOne, float threshold);

src/main/java/aquality/selenium/core/visualization/ImageComparator.java

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,39 @@
11
package aquality.selenium.core.visualization;
22

3+
import aquality.selenium.core.configurations.IVisualConfiguration;
4+
import com.google.inject.Inject;
5+
36
import java.awt.*;
47
import java.awt.image.BufferedImage;
58

69
public class ImageComparator implements IImageComparator {
7-
private static final int DEFAULT_THRESHOLD = 3;
810
private static final int THRESHOLD_DIVISOR = 255;
9-
private final int comparisonHeight = 16;
10-
private final int comparisonWidth = 16;
11+
private final IVisualConfiguration visualConfiguration;
12+
13+
@Inject
14+
public ImageComparator(IVisualConfiguration visualConfiguration) {
15+
this.visualConfiguration = visualConfiguration;
16+
}
17+
18+
private int getComparisonHeight() {
19+
return visualConfiguration.getComparisonHeight();
20+
}
21+
22+
private int getComparisonWidth() {
23+
return visualConfiguration.getComparisonWidth();
24+
}
1125

1226
public float percentageDifference(Image thisOne, Image theOtherOne, float threshold) {
1327
if (threshold < 0 || threshold > 1) {
1428
throw new IllegalArgumentException(String.format("Threshold should be between 0 and 1, but was [%s]", threshold));
1529
}
1630

17-
int intThreshold = Float.valueOf(threshold * THRESHOLD_DIVISOR).intValue();
31+
int intThreshold = (int) (threshold * THRESHOLD_DIVISOR);
1832
return percentageDifference(thisOne, theOtherOne, intThreshold);
1933
}
2034

2135
public float percentageDifference(Image thisOne, Image theOtherOne) {
22-
return percentageDifference(thisOne, theOtherOne, DEFAULT_THRESHOLD);
36+
return percentageDifference(thisOne, theOtherOne, visualConfiguration.getDefaultThreshold());
2337
}
2438

2539
protected float percentageDifference(Image thisOne, Image theOtherOne, int threshold) {
@@ -35,16 +49,16 @@ protected float percentageDifference(Image thisOne, Image theOtherOne, int thres
3549
}
3650
}
3751

38-
return diffPixels / (float) (comparisonWidth * comparisonHeight);
52+
return diffPixels / (float) (getComparisonWidth() * getComparisonHeight());
3953
}
4054

4155
protected int[][] getDifferences(Image thisOne, Image theOtherOne) {
4256
int[][] firstGray = getResizedGrayScaleValues(thisOne);
4357
int[][] secondGray = getResizedGrayScaleValues(theOtherOne);
4458

45-
int[][] differences = new int[comparisonWidth][comparisonHeight];
46-
for (int y = 0; y < comparisonHeight; y++) {
47-
for (int x = 0; x < comparisonWidth; x++) {
59+
int[][] differences = new int[getComparisonWidth()][getComparisonHeight()];
60+
for (int y = 0; y < getComparisonHeight(); y++) {
61+
for (int x = 0; x < getComparisonWidth(); x++) {
4862
differences[x][y] = (byte) Math.abs(firstGray[x][y] - secondGray[x][y]);
4963
}
5064
}
@@ -53,13 +67,11 @@ protected int[][] getDifferences(Image thisOne, Image theOtherOne) {
5367
}
5468

5569
protected int[][] getResizedGrayScaleValues(Image image) {
56-
BufferedImage resizedImage = new BufferedImage(comparisonWidth, comparisonHeight, BufferedImage.TYPE_BYTE_GRAY);
57-
Graphics2D graphics2D = resizedImage.createGraphics();
58-
graphics2D.drawImage(image, 0, 0, comparisonWidth, comparisonHeight, null);
59-
graphics2D.dispose();
60-
int[][] grayScale = new int[comparisonWidth][comparisonHeight];
61-
for (int y = 0; y < comparisonHeight; y++) {
62-
for (int x = 0; x < comparisonWidth; x++) {
70+
BufferedImage resizedImage = ImageFunctions.resize(image, getComparisonWidth(), getComparisonHeight());
71+
BufferedImage grayImage = ImageFunctions.grayscale(resizedImage);
72+
int[][] grayScale = new int[grayImage.getWidth()][grayImage.getHeight()];
73+
for (int y = 0; y < grayImage.getHeight(); y++) {
74+
for (int x = 0; x < grayImage.getWidth(); x++) {
6375
int pixel = resizedImage.getRGB(x, y);
6476
int red = (pixel >> 16) & 0xff;
6577
grayScale[x][y] = Math.abs(red);

src/main/java/aquality/selenium/core/visualization/ImageFunctions.java

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,13 @@
1919
* Image and screenshot extensions.
2020
*/
2121
public class ImageFunctions {
22+
private ImageFunctions() throws InstantiationException {
23+
throw new InstantiationException("Static ImageFunctions should not be initialized");
24+
}
25+
2226
/**
2327
* Represents given element's screenshot as an image.
28+
*
2429
* @param element given element.
2530
* @return image object.
2631
*/
@@ -30,6 +35,7 @@ public static BufferedImage getScreenshotAsImage(IElement element) {
3035

3136
/**
3237
* Represents given element's screenshot as an image.
38+
*
3339
* @param element given element.
3440
* @return image object.
3541
*/
@@ -45,17 +51,55 @@ public static BufferedImage getScreenshotAsImage(RemoteWebElement element) {
4551

4652
/**
4753
* Represents dimension of the given image.
54+
*
4855
* @param image given image.
4956
* @return size of the given image.
5057
*/
5158
public static Dimension getSize(Image image) {
5259
if (image instanceof RenderedImage) {
5360
RenderedImage renderedImage = (RenderedImage) image;
5461
return new Dimension(renderedImage.getWidth(), renderedImage.getHeight());
55-
}
56-
else {
62+
} else {
5763
return new Dimension(image.getWidth(null), image.getHeight(null));
5864
}
65+
}
5966

67+
/**
68+
* Gray-scaling the image.
69+
*
70+
* @param image source image.
71+
* @return gray-scaled image.
72+
*/
73+
public static BufferedImage grayscale(BufferedImage image) {
74+
BufferedImage result = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
75+
for (int y = 0; y < result.getHeight(); y++) {
76+
for (int x = 0; x < result.getWidth(); x++) {
77+
int pixel = image.getRGB(x, y);
78+
int a = (pixel >> 24) & 0xff;
79+
int r = (pixel >> 16) & 0xff;
80+
int g = (pixel >> 8) & 0xff;
81+
int b = pixel & 0xff;
82+
int average = (r + g + b) / 3;
83+
pixel = (a << 24) | (average << 16) | (average << 8) | average;
84+
result.setRGB(x, y, pixel);
85+
}
86+
}
87+
return result;
88+
}
89+
90+
/**
91+
* Resizes image giving higher priority to image smoothness than scaling speed.
92+
* @param image source image.
93+
* @param width target width.
94+
* @param height target height.
95+
* @return resized image.
96+
*/
97+
public static BufferedImage resize(Image image, int width, int height) {
98+
BufferedImage resizedImage = new BufferedImage(width, height, TYPE_INT_RGB);
99+
Graphics graphics = resizedImage.getGraphics();
100+
Image scaledImage = image.getScaledInstance(width, height, Image.SCALE_SMOOTH);
101+
graphics.drawImage(scaledImage, 0, 0, width, height, null);
102+
graphics.dispose();
103+
return resizedImage;
60104
}
61105
}

src/test/java/tests/visualization/VisualStateProviderTests.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22

33
import aquality.selenium.core.visualization.IVisualStateProvider;
44
import aquality.selenium.core.visualization.ImageFunctions;
5+
import aquality.selenium.core.waitings.IConditionalWait;
56
import org.testng.Assert;
67
import org.testng.annotations.BeforeMethod;
78
import org.testng.annotations.Test;
9+
import tests.applications.browser.AqualityServices;
810
import tests.applications.browser.ITheInternetPageTest;
911
import theinternet.DynamicLoadingForm;
1012
import theinternet.TheInternetPage;
@@ -81,7 +83,8 @@ public void testGetPercentageDifferenceForDifferentElementsWithFullThreshold() {
8183
public void testGetPercentageDifferenceForSimilarElements() throws InterruptedException {
8284
startLoading();
8385
Image firstImage = getLoadingVisual().getImage();
84-
Thread.sleep(100);
86+
AqualityServices.get(IConditionalWait.class).waitFor(
87+
() -> firstImage.getHeight(null) < getLoadingVisual().getSize().getHeight());
8588
Assert.assertNotEquals(getLoadingVisual().getDifference(firstImage, 0), 0);
8689
Assert.assertTrue(getLoadingVisual().getDifference(firstImage, 0.2f) <= 0.3);
8790
Assert.assertTrue(getLoadingVisual().getDifference(firstImage, 0.4f) <= 0.2);

0 commit comments

Comments
 (0)