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