package org.deegree.matcher.image; import static javax.imageio.ImageIO.read; import java.awt.image.BufferedImage; import java.awt.image.PixelGrabber; import java.io.File; import java.io.IOException; import java.util.Arrays; import javax.imageio.ImageIO; import org.hamcrest.BaseMatcher; import org.hamcrest.Description; import org.hamcrest.Matcher; /** * Matcher for images. * * @author <a href="mailto:stenger@lat-lon.de">Dirk Stenger</a> * @author last edited by: $Author: stenger $ * * @version $Revision: $, $Date: $ */ public final class ImageMatcher { private static boolean INVERTED = true; private static boolean NOT_INVERTED = false; private ImageMatcher() { } /** * Matcher to check whether image has same dimension as source file. * * @param sourceFile * source file to compare with * @return a {@link Matcher} * @throws IOException */ public static Matcher<File> hasSameDimension( File sourceFile ) throws IOException { BufferedImage sourceImage = read( sourceFile ); final int heightSource = sourceImage.getHeight(); final int widthSource = sourceImage.getWidth(); return new DimensionMatcher<File>( heightSource, widthSource ); } /** * Matcher to check whether image has same pixels as source file. * * @param sourceFile * source file to compare with * @return a {@link Matcher} * @throws Exception */ public static Matcher<File> hasSamePixels( File sourceFile ) throws Exception { BufferedImage sourceImage = ImageIO.read( sourceFile ); PixelGrabber sourceGrabber = new PixelGrabber( sourceImage, 0, 0, -1, -1, false ); final int[] sourcePixelsToCompare = calculatePixels( sourceGrabber ); return new PixelMatcher<File>( sourcePixelsToCompare, NOT_INVERTED ); } /** * Matcher to check whether image has not same pixels as source file. * * @param sourceFile * to compare with * @return a {@link Matcher} * @throws Exception */ public static Matcher<File> hasNotSamePixels( File sourceFile ) throws Exception { BufferedImage sourceImage = ImageIO.read( sourceFile ); PixelGrabber sourceGrabber = new PixelGrabber( sourceImage, 0, 0, -1, -1, false ); final int[] sourcePixelsToCompare = calculatePixels( sourceGrabber ); return new PixelMatcher<File>( sourcePixelsToCompare, INVERTED ); } private static int[] calculatePixels( PixelGrabber destinationGrabber ) throws InterruptedException { int[] pixels = null; if ( destinationGrabber.grabPixels() ) { pixels = (int[]) destinationGrabber.getPixels(); } return pixels; } /** * Matcher to compare dimensions * * @param <T> */ private static class DimensionMatcher<T> extends BaseMatcher<T> { private final int heightSource; private final int widthSource; DimensionMatcher( int heightSource, int widthSource ) { this.heightSource = heightSource; this.widthSource = widthSource; } @Override public boolean matches( Object item ) { BufferedImage destinationImage; try { destinationImage = read( (File) item ); int heightDestination = destinationImage.getHeight(); int widthDestination = destinationImage.getWidth(); return heightDestination == heightSource && widthDestination == widthSource; } catch ( IOException e ) { e.printStackTrace(); } return false; } @Override public void describeTo( Description description ) { description.appendText( "Should have the same width and height as the source ( " + widthSource + " * " + heightSource + ")!" ); } } private static class PixelMatcher<T> extends BaseMatcher<T> { private int[] sourcePixelsToCompare; private boolean inverse; PixelMatcher( int[] sourcePixelsToCompare, boolean inverse ) { this.sourcePixelsToCompare = sourcePixelsToCompare; this.inverse = inverse; } @Override public boolean matches( Object item ) { BufferedImage destinationImage; try { destinationImage = read( (File) item ); PixelGrabber destinationGrabber = new PixelGrabber( destinationImage, 0, 0, -1, -1, false ); int[] destinationPixels = calculatePixels( destinationGrabber ); boolean matching = Arrays.equals( destinationPixels, sourcePixelsToCompare ); return inverse ? !matching : matching; } catch ( Exception e ) { e.printStackTrace(); } return false; } @Override public void describeTo( Description description ) { String inverseString = inverse ? "not " : ""; description.appendText( "Should " + inverseString + "contain the same pixels as the source!" ); } } }