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 28 import java.awt.image.BufferedImage; 29 import java.io.File; 30 import java.io.IOException; 31 import org.jemmy.Dimension; 32 import org.jemmy.JemmyException; 33 import org.jemmy.control.Wrap; 34 import org.jemmy.env.Environment; 35 import org.jemmy.image.pixel.*; 36 37 38 /** 39 * 40 * @author shura 41 */ 42 public class AWTImage implements Image, WriteableRaster { 43 44 /** 45 * 46 */ 47 public static final String OUTPUT = AWTImage.class.getName() + ".OUTPUT"; 48 public static final String PNG_FILE = ".png"; 49 50 /** 51 * Get the value of imageRoot. The field is used to store images by relative 52 * path within the root. Images should be pointed out by full file names if 53 * the value is null. 54 * 55 * @return the value of imageRoot 56 */ 57 public static File getImageRoot() { 58 ImageStore res = Environment.getEnvironment().getProperty(ImageStore.class); 59 if(!(res instanceof PNGFileImageStore)) { 60 throw new IllegalStateException("Unsupported ImageStore: " + res.getClass().getName()); 61 } 62 return ((PNGFileImageStore)res).getRoot(); 63 } 64 65 /** 66 * Set the value of imageRoot. If null, an image ID should be full path. 67 * 68 * @param imageRoot new value of imageRoot 69 */ 70 public static void setImageRoot(File imageRoot) { 71 Environment.getEnvironment().setProperty(ImageStore.class, new PNGFileImageStore(imageRoot)); 72 } 73 74 /** 75 * Gets comparator to be used by default. 76 * 77 * @see Wrap#waitImage(org.jemmy.image.Image, java.lang.String, 78 * java.lang.String) 79 * @see ImageComparator 80 * @return default comparator 81 */ 82 public static ImageComparator getComparator() { 83 return Environment.getEnvironment().getProperty(ImageComparator.class); 84 } 85 86 /** 87 * Sets comparator to be used by default. 88 * 89 * @see Wrap#waitImage(org.jemmy.image.Image, java.lang.String, 90 * java.lang.String) 91 * @see ImageComparator 92 * @param comparator 93 */ 94 public static void setComparator(ImageComparator comparator) { 95 Environment.getEnvironment().setProperty(ImageComparator.class, comparator); 96 } 97 98 static { 99 Environment.getEnvironment().setPropertyIfNotSet(ImageComparator.class, 100 new BufferedImageComparator(Environment.getEnvironment())); 101 Environment.getEnvironment().setPropertyIfNotSet(ImageStore.class, new PNGFileImageStore()); 102 } 103 104 private BufferedImage image; 105 106 /** 107 * Creates an instance 108 * 109 * @param img 110 */ 111 public AWTImage(BufferedImage img) { 112 this.image = img; 113 } 114 115 public BufferedImage getTheImage() { 116 return image; 117 } 118 119 /** 120 * Compares using current comparator. 121 * 122 * @see AWTImage#getComparator() 123 * @param img 124 * @return diff image. 125 */ 126 public Image compareTo(Image img) { 127 return getComparator().compare(this, img); 128 } 129 130 /** 131 * Saves to a filesystem. fileName is expected to be a full path, unless 132 * imageRoot is specified. ".png" extension is added automatically if not 133 * specified. 134 * 135 * @see AWTImage#getImageRoot() 136 * @param fileName full or relative file name 137 */ 138 public void save(String fileName) { 139 try { 140 String fullPath = fileName; 141 File imageRoot = getImageRoot(); 142 if (imageRoot != null) { 143 fullPath = imageRoot.getAbsolutePath() + File.separator + fileName; 144 } 145 if (!fullPath.toLowerCase().endsWith(PNG_FILE)) { 146 fullPath += PNG_FILE; 147 } 148 new PNGImageSaver().save(image, fullPath); 149 Environment.getEnvironment().getOutput(OUTPUT).println("Image saved to " + fullPath); 150 } catch (IOException ex) { 151 throw new JemmyException("Unable to save image", ex, fileName); 152 } 153 } 154 155 public Dimension getSize() { 156 return new Dimension(image.getWidth(), image.getHeight()); 157 } 158 159 public void getColors(int x, int y, double[] colors) { 160 int orig = image.getRGB(x, y); 161 int ivalue; 162 for (Raster.Component c : getSupported()) { 163 switch (c) { 164 case ALPHA: 165 ivalue = (orig & 0xFF000000) >>> 0x18; 166 break; 167 case RED: 168 ivalue = (orig & 0xFF0000) >>> 0x10; 169 break; 170 case GREEN: 171 ivalue = (orig & 0xFF00) >>> 0x8; 172 break; 173 case BLUE: 174 ivalue = (orig & 0xFF); 175 break; 176 default: 177 throw new IllegalArgumentException("Unknown color component" + c); 178 } 179 colors[PixelImageComparator.arrayIndexOf(getSupported(), c)] = (double) ivalue / 0xFF; 180 } 181 } 182 183 public void setColors(int x, int y, double[] colors) { 184 int rgb = 0; 185 double value; 186 int ivalue; 187 for (Raster.Component c : getSupported()) { 188 value = colors[PixelImageComparator.arrayIndexOf(getSupported(), c)]; 189 if (value < 0 || value > 1) { 190 throw new IllegalArgumentException("Color component value should be within (0, 1). Gotten: " + value); 191 } 192 ivalue = (int) Math.round(value * 0xFF); 193 if (ivalue > 0xFF) { 194 throw new IllegalStateException("Component value is greater than 0xFF: " + ivalue); 195 } 196 switch (c) { 197 case ALPHA: 198 rgb |= (ivalue << 0x18); 199 break; 200 case RED: 201 rgb |= (ivalue << 0x10); 202 break; 203 case GREEN: 204 rgb |= (ivalue << 0x8); 205 break; 206 case BLUE: 207 rgb |= ivalue; 208 break; 209 default: 210 throw new IllegalArgumentException("Unknown color component: " + c); 211 } 212 } 213 getTheImage().setRGB(x, y, rgb); 214 } 215 216 public Component[] getSupported() { 217 return new Component[]{Component.RED, Component.BLUE, Component.GREEN, Component.ALPHA}; 218 } 219 }