1 /* 2 * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package org.jemmy.image; 26 27 import java.awt.Graphics2D; 28 import java.awt.image.BufferedImage; 29 import org.jemmy.Dimension; 30 import org.jemmy.env.Environment; 31 import org.jemmy.env.TestOut; 32 import org.jemmy.image.pixel.Raster; 33 import org.jemmy.image.pixel.RasterComparator; 34 import org.jemmy.image.pixel.ResizeComparator; 35 36 /** 37 * Comparator that makes image sizes equal to compare them with other comparator 38 * most of them work only for the images with equal dimensions. 39 * 40 * It is controlled by three parameters: <li>Resize Mode - defines way of 41 * resizing images that are being compared. One of the following constants: <ul> <li>{@linkplain ResizeMode#NO_RESIZE NO_RESIZE},</li> <li>{@linkplain ResizeMode#PROPORTIONAL_RESIZE PROPORTIONAL_RESIZE},</li> <li>{@linkplain ResizeMode#ARBITRARY_RESIZE ARBITRARY_RESIZE}.</li></ul> 42 * Default value is {@linkplain ResizeMode#PROPORTIONAL_RESIZE}.</li> <li>Resize 43 * Hint - defines the way of images scaling that is specified when {@linkplain java.awt.Image#getScaledInstance(int, int, int) 44 * Image.getScaledInstance()} method is invoked. One of the Image.SCALE_XXX is 45 * expected. Default value is 46 * {@linkplain java.awt.Image#SCALE_DEFAULT SCALE_DEFAULT}.</li> <li>Proportion 47 * Distortion Threshold - defines maximum proportion distortion that is used in {@linkplain ResizeMode#PROPORTIONAL_RESIZE 48 * PROPORTIONAL_RESIZE} mode to deal with cases when rounding and other problems 49 * could cause sizes to be not ideally proportional.<p/> 50 * Threshold value is applied in the following way: {@code Math.abs(image.getSize() * scale 51 * - size) / image.getSize() > PROPORTION_DISTORTION_THRESHOLD}, where {@code image.getSize()} 52 * is both image dimensions and {@code size} is target width and height (which 53 * is defined as mininum of sizes of two images) and scale is the scale factor 54 * that scales the particular image to fit the width and height. 55 * <p/> 56 * Default value is 0.02 so as much as 2% of width/height could differ (around 5 57 * in 0-255 color component values).</li> 58 * 59 * @author mrkam 60 */ 61 public class ResizeImageComparator extends ResizeComparator { 62 63 /** 64 * Indentifies output where resize details are printed. Output is disabled 65 * by default. 66 * 67 * @see Environment#getOutput(java.lang.String) 68 */ 69 public static final String OUTPUT = ResizeImageComparator.class.getName() 70 + ".OUTPUT"; 71 72 static { 73 Environment.getEnvironment().setOutput(OUTPUT, TestOut.getNullOutput()); 74 } 75 ResizeMode resizeMode; 76 int hint; 77 double propDistThreshold; 78 79 /** 80 * Resize Modes 81 * 82 * @see 83 * #ResizeImageComparator(org.jemmy.image.ResizeImageComparator.ResizeMode, 84 * org.jemmy.image.ImageComparator) 85 * @see 86 * #ResizeImageComparator(org.jemmy.image.ResizeImageComparator.ResizeMode, 87 * int, double, org.jemmy.image.ImageComparator) 88 */ 89 public static enum ResizeMode { 90 91 /** 92 * Images are never resized. Original images are always compared. 93 */ 94 NO_RESIZE, 95 /** 96 * Images are resized only if they have exactly or almost proportional 97 * sizes which is controlled by {@code proportionDistortion} parameter. 98 * If images have different proportions no resize is done and original 99 * images are compared. 100 * 101 * @see 102 * #ResizeImageComparator(org.jemmy.image.ResizeImageComparator.ResizeMode, 103 * int, double, org.jemmy.image.ImageComparator) 104 */ 105 PROPORTIONAL_RESIZE, 106 /** 107 * Images are always resized to match both width and height and then 108 * compared. 109 */ 110 ARBITRARY_RESIZE 111 } 112 113 /** 114 * Creates ResizeImageComparator with default resize settings: <li>resize 115 * mode: {@linkplain ResizeMode#PROPORTIONAL_RESIZE ResizeMode.PROPORTIONAL_RESIZE}.</li> 116 * <li>proportion distortion threshold: 0.02.</li> <li>resize hint: {@linkplain java.awt.Image#SCALE_DEFAULT Image.SCALE_DEFAULT}.</li> 117 * 118 * @param subComparator comparator to compare images after resize. 119 * @see java.awt.Image#getScaledInstance(int, int, int) 120 * @see ResizeMode 121 * @see ResizeImageComparator 122 */ 123 public ResizeImageComparator(ImageComparator subComparator) { 124 super(subComparator, ResizeComparator.Mode.LEFT); 125 this.resizeMode = ResizeMode.PROPORTIONAL_RESIZE; 126 this.hint = java.awt.Image.SCALE_DEFAULT; 127 this.propDistThreshold = 0.02; 128 } 129 130 /** 131 * Creates ResizeImageComparator with the specified resize mode and default 132 * settings for other parameters: <li>proportion distortion threshold: 133 * 0.02.</li> <li>resize hint: {@linkplain java.awt.Image#SCALE_DEFAULT Image.SCALE_DEFAULT}.</li> 134 * 135 * @param resizeMode resize mode for this comparator. 136 * @param subComparator comparator to compare images after resize. 137 * @see ResizeMode 138 * @see ResizeImageComparator 139 */ 140 public ResizeImageComparator(ResizeMode resizeMode, 141 ImageComparator subComparator) { 142 this(subComparator); 143 this.resizeMode = resizeMode; 144 } 145 146 /** 147 * Creates ResizeImageComparator with the following settings: <li>resize 148 * mode: {@linkplain ResizeMode#PROPORTIONAL_RESIZE ResizeMode.PROPORTIONAL_RESIZE}.</li> 149 * <li>specified proportion distortion threshold.</li> <li>resize hint: {@linkplain java.awt.Image#SCALE_DEFAULT Image.SCALE_DEFAULT}.</li> 150 * 151 * @param propDistThreshold proportion distortion threshold. 152 * @param subComparator comparator to compare images after resize. 153 * @see ResizeImageComparator 154 */ 155 public ResizeImageComparator(double propDistThreshold, 156 ImageComparator subComparator) { 157 this(subComparator); 158 this.propDistThreshold = propDistThreshold; 159 } 160 161 /** 162 * Creates ResizeImageComparator with specified settings. 163 * 164 * @param resizeMode Resize mode. 165 * @param propDistThreshold Proportion distortion threshold. 166 * @param hint Resize hint. 167 * @param subComparator comparator to compare images after resize. 168 * @see ResizeImageComparator 169 * @see ResizeMode 170 */ 171 public ResizeImageComparator(ResizeMode resizeMode, double propDistThreshold, 172 int hint, ImageComparator subComparator) { 173 this(subComparator); 174 this.resizeMode = resizeMode; 175 this.hint = hint; 176 this.propDistThreshold = propDistThreshold; 177 } 178 179 @Override 180 public Image resize(Image image, Dimension size) { 181 Dimension isize = getSize(image); 182 double scalex = (double) size.width / isize.width; 183 double scaley = (double) size.height / isize.height; 184 switch (resizeMode) { 185 case NO_RESIZE: 186 return image; 187 case PROPORTIONAL_RESIZE: 188 if (Math.abs(scalex - scaley) > propDistThreshold) { 189 return null; 190 } 191 case ARBITRARY_RESIZE: 192 BufferedImage res = new BufferedImage(size.width, size.height, ((AWTImage) image).getTheImage().getType()); 193 java.awt.Image scaled = ((AWTImage) image).getTheImage().getScaledInstance( 194 size.width, size.height, hint); 195 Graphics2D g = res.createGraphics(); 196 g.drawImage(scaled, 0, 0, null); 197 g.dispose(); 198 return new AWTImage(res); 199 default: 200 return null; 201 } 202 } 203 @Override 204 public String getID() { 205 return ResizeImageComparator.class.getName() + "(" 206 + getSubComparator().getID() + ")"; 207 } 208 209 @Override 210 public Dimension getSize(Image image) { 211 BufferedImage bi = ((AWTImage)image).getTheImage(); 212 return new Dimension(bi.getWidth(), bi.getHeight()); 213 } 214 215 }