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