com.assertthat.selenium_shutterbug.utils.image.ImageProcessor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of selenium-shutterbug Show documentation
Show all versions of selenium-shutterbug Show documentation
Utility library to create customized screenshots using Selenium WebDriver and Java AWT
/*
* Copyright (c) 2016, Glib Briia Glib Briia
* Distributed under the terms of the MIT License
*/
package com.assertthat.selenium_shutterbug.utils.image;
import com.assertthat.selenium_shutterbug.utils.image.model.ImageData;
import com.assertthat.selenium_shutterbug.utils.web.Coordinates;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ColorConvertOp;
import java.awt.image.ColorModel;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.awt.image.PixelGrabber;
import java.io.ByteArrayInputStream;
import java.io.IOException;
/**
* Created by Glib_Briia on 17/06/2016.
*/
public class ImageProcessor {
private static final int ARCH_SIZE = 10;
private static final float[] matrix = new float[49];
private static double pixelError = Double.MAX_VALUE;
static {
for (int i = 0; i < 49; i++)
matrix[i] = 1.0f / 49.0f;
}
public static BufferedImage blur(BufferedImage sourceImage) {
BufferedImageOp options = new ConvolveOp(new Kernel(7, 7, matrix), ConvolveOp.EDGE_NO_OP, null);
return options.filter(sourceImage, null);
}
public static BufferedImage highlight(BufferedImage sourceImage, Coordinates coords, Color color, int lineWidth) {
byte defaultLineWidth = 3;
Graphics2D g = sourceImage.createGraphics();
g.setPaint(color);
g.setStroke(new BasicStroke(lineWidth == 0 ? defaultLineWidth : lineWidth));
g.drawRoundRect(coords.getX(), coords.getY(), coords.getWidth(), coords.getHeight(), ARCH_SIZE, ARCH_SIZE);
g.dispose();
return sourceImage;
}
public static BufferedImage addText(BufferedImage sourceImage, int x, int y, String text, Color color, Font font) {
Graphics2D g = sourceImage.createGraphics();
g.setPaint(color);
g.setFont(font);
g.drawString(text, x, y);
g.dispose();
return sourceImage;
}
public static BufferedImage getElement(BufferedImage sourceImage, Coordinates coords) {
return sourceImage.getSubimage(coords.getX(), coords.getY(), coords.getWidth(), coords.getHeight());
}
public static BufferedImage blurArea(BufferedImage sourceImage, Coordinates coords) {
BufferedImage blurredImage = blur(sourceImage.getSubimage(coords.getX(), coords.getY(), coords.getWidth(), coords.getHeight()));
return getBufferedImage(sourceImage, coords, blurredImage, sourceImage);
}
public static BufferedImage monochromeArea(BufferedImage sourceImage, Coordinates coords) {
BufferedImage monochromedImage = convertToGrayAndWhite(sourceImage.getSubimage(coords.getX(), coords.getY(), coords.getWidth(), coords.getHeight()));
return getBufferedImage(sourceImage, coords, monochromedImage, sourceImage);
}
public static BufferedImage blurExceptArea(BufferedImage sourceImage, Coordinates coords) {
BufferedImage subImage = sourceImage.getSubimage(coords.getX(), coords.getY(), coords.getWidth(), coords.getHeight());
BufferedImage blurredImage = blur(sourceImage);
return getBufferedImage(sourceImage, coords, subImage, blurredImage);
}
private static BufferedImage getBufferedImage(BufferedImage sourceImage, Coordinates coords, BufferedImage subImage, BufferedImage blurredImage) {
BufferedImage combined = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g = combined.createGraphics();
g.drawImage(blurredImage, 0, 0, null);
g.drawImage(subImage, coords.getX(), coords.getY(), null);
g.dispose();
return combined;
}
public static BufferedImage cropAround(BufferedImage sourceImage, Coordinates coords, int offsetX, int offsetY) {
return sourceImage.getSubimage(coords.getX() - offsetX, coords.getY() - offsetY, coords.getWidth() + offsetX * 2, coords.getHeight() + offsetY * 2);
}
public static BufferedImage cutOut(BufferedImage sourceImage, Coordinates coords, int offsetX, int offsetY) {
Graphics bg = sourceImage.getGraphics();
bg.setColor(Color.white);
bg.fillRect(coords.getX() - offsetX, coords.getY() - offsetY, coords.getScrollWidth() + offsetX * 2, coords.getScrollHeight() + offsetY * 2);
return sourceImage;
}
public static BufferedImage addTitle(BufferedImage sourceImage, String title, Color color, Font textFont) {
int textOffset = 5;
BufferedImage combined = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight() + textFont.getSize(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g = combined.createGraphics();
g.drawImage(sourceImage, 0, textFont.getSize() + textOffset, null);
addText(combined, 0, textFont.getSize(), title, color, textFont);
g.dispose();
return combined;
}
public static BufferedImage convertToGrayAndWhite(BufferedImage sourceImage) {
ColorConvertOp op = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
op.filter(sourceImage, sourceImage);
return sourceImage;
}
public static boolean imagesAreEquals(BufferedImage image1, BufferedImage image2, double deviation) {
ImageData image1Data = new ImageData(image1);
ImageData image2Data = new ImageData(image2);
if (image1Data.notEqualsDimensions(image2Data)) {
throw new UnableToCompareImagesException("Images dimensions mismatch: image1 - " + image1Data.getWidth() + "x" + image1Data.getHeight() + "; image2 - " + image2Data.getWidth() + "x" + image2Data.getHeight());
}
return image1Data.equalsEachPixels(image2Data, deviation);
}
/**
* Extends the functionality of imagesAreEqualsWithDiff, but creates a third BufferedImage and applies pixel manipulation to it.
*
* @param image1 The first image to compare
* @param image2 The second image to compare
* @param pathFileName The output path filename for the third image, if null then is ignored
* @param deviation The upper limit of the pixel deviation for the test
* @return If the test passes
*/
public static boolean imagesAreEqualsWithDiff(BufferedImage image1, BufferedImage image2, String pathFileName, double deviation) {
ImageData image1Data = new ImageData(image1);
ImageData image2Data = new ImageData(image2);
if (image1Data.notEqualsDimensions(image2Data)) {
throw new UnableToCompareImagesException("Images dimensions mismatch: image1 - " + image1Data.getWidth() + "x" + image1Data.getHeight() + "; image2 - " + image2Data.getWidth() + "x" + image2Data.getHeight());
}
return image1Data.equalsEachPixelsWithCreateDifferencesImage(image2Data, deviation, pathFileName);
}
public static BufferedImage scale(BufferedImage source, double ratio) {
return cropAndScale(source, ratio, 1.0, 1.0);
}
public static BufferedImage cropAndScale(BufferedImage source, double ratio, double cropWidth, double cropHeight) {
int w = (int) (source.getWidth() * ratio);
int h = (int) (source.getHeight() * ratio);
BufferedImage scaledImage = createAndDrawImage(source, w, h);
return scaledImage.getSubimage(0, 0, (int) (w * cropWidth), (int) (h * cropHeight));
}
public static BufferedImage cropAndScale(BufferedImage source, double ratio, int maxWidth, int maxHeight) {
int w = (int) (source.getWidth() * ratio);
int h = (int) (source.getHeight() * ratio);
BufferedImage scaledImage = createAndDrawImage(source, w, h);
if (maxWidth != -1 && w > maxWidth) {
w = maxWidth;
}
if (maxHeight != -1 && h > maxHeight) {
h = maxHeight;
}
return scaledImage.getSubimage(0, 0, w, h);
}
private static BufferedImage createAndDrawImage(BufferedImage source, int w, int h) {
BufferedImage scaledImage = getCompatibleImage(w, h, source);
Graphics2D resultGraphics = scaledImage.createGraphics();
resultGraphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BICUBIC);
resultGraphics.drawImage(source, 0, 0, w, h, null);
resultGraphics.dispose();
return scaledImage;
}
private static BufferedImage getCompatibleImage(int w, int h, BufferedImage source) {
BufferedImage bImage = null;
try {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gd = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gd.getDefaultConfiguration();
bImage = gc.createCompatibleImage(w, h);
} catch (HeadlessException e) {
// The system does not have a screen
}
if (bImage == null) {
boolean hasAlpha = hasAlpha(source);
int type = BufferedImage.TYPE_INT_RGB;
if (hasAlpha) {
type = BufferedImage.TYPE_INT_ARGB;
}
bImage = new BufferedImage(w, h, type);
}
return bImage;
}
public static boolean hasAlpha(Image image) {
// If buffered image, the color model is readily available
if (image instanceof BufferedImage) {
BufferedImage bImage = (BufferedImage) image;
return bImage.getColorModel().hasAlpha();
}
// Use a pixel grabber to retrieve the image's color model;
// grabbing a single pixel is usually sufficient
PixelGrabber pg = new PixelGrabber(image, 0, 0, 1, 1, false);
try {
pg.grabPixels();
} catch (InterruptedException ignored) {
}
// Get the image's color model
ColorModel cm = pg.getColorModel();
return cm.hasAlpha();
}
public static BufferedImage createImageFromBytes(byte[] imageData) {
ByteArrayInputStream bais = new ByteArrayInputStream(imageData);
try {
return ImageIO.read(bais);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}