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 java.awt.Graphics2D; 26 import java.awt.image.BufferedImage; 27 import org.jemmy.Dimension; 28 import org.jemmy.env.Environment; 29 import org.jemmy.env.TestOut; 30 import org.jemmy.image.pixel.Raster; 31 import org.jemmy.image.pixel.RasterComparator; 32 import org.jemmy.image.pixel.ResizeComparator; 33 34 /** 35 * Comparator that makes image sizes equal to compare them with other comparator 36 * most of them work only for the images with equal dimensions. 37 * 38 * It is controlled by three parameters: <li>Resize Mode - defines way of 39 * 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> 40 * Default value is {@linkplain ResizeMode#PROPORTIONAL_RESIZE}.</li> <li>Resize 41 * Hint - defines the way of images scaling that is specified when {@linkplain java.awt.Image#getScaledInstance(int, int, int) 42 * Image.getScaledInstance()} method is invoked. One of the Image.SCALE_XXX is 43 * expected. Default value is 44 * {@linkplain java.awt.Image#SCALE_DEFAULT SCALE_DEFAULT}.</li> <li>Proportion 45 * Distortion Threshold - defines maximum proportion distortion that is used in {@linkplain ResizeMode#PROPORTIONAL_RESIZE 46 * PROPORTIONAL_RESIZE} mode to deal with cases when rounding and other problems 47 * could cause sizes to be not ideally proportional.<p/> 48 * Threshold value is applied in the following way: {@code Math.abs(image.getSize() * scale 49 * - size) / image.getSize() > PROPORTION_DISTORTION_THRESHOLD}, where {@code image.getSize()} 50 * is both image dimensions and {@code size} is target width and height (which 51 * is defined as mininum of sizes of two images) and scale is the scale factor 52 * that scales the particular image to fit the width and height. 53 * <p/> 54 * Default value is 0.02 so as much as 2% of width/height could differ (around 5 55 * in 0-255 color component values).</li> 56 * 57 * @author mrkam 58 */ 59 public class ResizeImageComparator extends ResizeComparator { 60 61 /** 62 * Indentifies output where resize details are printed. Output is disabled 63 * by default. 64 * 65 * @see Environment#getOutput(java.lang.String) 66 */ 67 public static final String OUTPUT = ResizeImageComparator.class.getName() 68 + ".OUTPUT"; 69 70 static { 71 Environment.getEnvironment().setOutput(OUTPUT, TestOut.getNullOutput()); 72 } 73 ResizeMode resizeMode; 74 int hint; 75 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 super(subComparator, ResizeComparator.Mode.LEFT); 123 this.resizeMode = ResizeMode.PROPORTIONAL_RESIZE; 124 this.hint = java.awt.Image.SCALE_DEFAULT; 125 this.propDistThreshold = 0.02; 126 } 127 128 /** 129 * Creates ResizeImageComparator with the specified resize mode and default 130 * settings for other parameters: <li>proportion distortion threshold: 131 * 0.02.</li> <li>resize hint: {@linkplain java.awt.Image#SCALE_DEFAULT Image.SCALE_DEFAULT}.</li> 132 * 133 * @param resizeMode resize mode for this comparator. 134 * @param subComparator comparator to compare images after resize. 135 * @see ResizeMode 136 * @see ResizeImageComparator 137 */ 138 public ResizeImageComparator(ResizeMode resizeMode, 139 ImageComparator subComparator) { 140 this(subComparator); 141 this.resizeMode = resizeMode; 142 } 143 144 /** 145 * Creates ResizeImageComparator with the following settings: <li>resize 146 * mode: {@linkplain ResizeMode#PROPORTIONAL_RESIZE ResizeMode.PROPORTIONAL_RESIZE}.</li> 147 * <li>specified proportion distortion threshold.</li> <li>resize hint: {@linkplain java.awt.Image#SCALE_DEFAULT Image.SCALE_DEFAULT}.</li> 148 * 149 * @param propDistThreshold proportion distortion threshold. 150 * @param subComparator comparator to compare images after resize. 151 * @see ResizeImageComparator 152 */ 153 public ResizeImageComparator(double propDistThreshold, 154 ImageComparator subComparator) { 155 this(subComparator); 156 this.propDistThreshold = propDistThreshold; 157 } 158 159 /** 160 * Creates ResizeImageComparator with specified settings. 161 * 162 * @param resizeMode Resize mode. 163 * @param propDistThreshold Proportion distortion threshold. 164 * @param hint Resize hint. 165 * @param subComparator comparator to compare images after resize. 166 * @see ResizeImageComparator 167 * @see ResizeMode 168 */ 169 public ResizeImageComparator(ResizeMode resizeMode, double propDistThreshold, 170 int hint, ImageComparator subComparator) { 171 this(subComparator); 172 this.resizeMode = resizeMode; 173 this.hint = hint; 174 this.propDistThreshold = propDistThreshold; 175 } 176 177 @Override 178 public Image resize(Image image, Dimension size) { 179 Dimension isize = getSize(image); 180 double scalex = (double) size.width / isize.width; 181 double scaley = (double) size.height / isize.height; 182 switch (resizeMode) { 183 case NO_RESIZE: 184 return image; 185 case PROPORTIONAL_RESIZE: 186 if (Math.abs(scalex - scaley) > propDistThreshold) { 187 return null; 188 } 189 case ARBITRARY_RESIZE: 190 BufferedImage res = new BufferedImage(size.width, size.height, ((AWTImage) image).getTheImage().getType()); 191 java.awt.Image scaled = ((AWTImage) image).getTheImage().getScaledInstance( 192 size.width, size.height, hint); 193 Graphics2D g = res.createGraphics(); 194 g.drawImage(scaled, 0, 0, null); 195 g.dispose(); 196 return new AWTImage(res); 197 default: 198 return null; 199 } 200 } 201 @Override 202 public String getID() { 203 return ResizeImageComparator.class.getName() + "(" 204 + getSubComparator().getID() + ")"; 205 } 206 207 @Override 208 public Dimension getSize(Image image) { 209 BufferedImage bi = ((AWTImage)image).getTheImage(); 210 return new Dimension(bi.getWidth(), bi.getHeight()); 211 } 212 213 }