1 /*
   2  * Copyright (c) 2016, 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 
  24 /*
  25  * @test
  26  * @key headful
  27  * @bug     8139183
  28  * @summary Test verifies whether alpha channel of a translucent
  29  *          image is proper or not after scaling through drawImage.
  30  * @run     main ScaledImageAlphaTest
  31  */
  32 
  33 import java.awt.AlphaComposite;
  34 import java.awt.Color;
  35 import java.awt.Graphics2D;
  36 import java.awt.GraphicsConfiguration;
  37 import java.awt.GraphicsEnvironment;
  38 import java.awt.Transparency;
  39 import java.awt.image.BufferedImage;
  40 import java.awt.image.VolatileImage;
  41 
  42 public class ScaledImageAlphaTest {
  43 
  44     static final int translucentAlpha = 128, opaqueAlpha = 255;
  45     static final int[] translucentVariants = new int[] {
  46         BufferedImage.TYPE_INT_ARGB,
  47         BufferedImage.TYPE_INT_ARGB_PRE,
  48         BufferedImage.TYPE_4BYTE_ABGR,
  49         BufferedImage.TYPE_4BYTE_ABGR_PRE
  50     };
  51     static final int[] alphaValues = new int[] {
  52         translucentAlpha,
  53         opaqueAlpha
  54     };
  55     static int width = 50, height = 50;
  56     static int scaleX = 5, scaleY = 5, scaleWidth = 40, scaleHeight = 40;
  57 
  58     private static void verifyAlpha(Color color, int alpha) {
  59 
  60         /* if extracted alpha value is equal alpha that we set
  61          * for background color, alpha channel is not lost
  62          * while scaling otherwise we have lost alpha channel.
  63          */
  64         int extractedAlpha = color.getAlpha();
  65 
  66         if (extractedAlpha != alpha) {
  67             throw new RuntimeException("Alpha channel for background"
  68                     + " is lost while scaling");
  69         }
  70     }
  71 
  72     private static void validateBufferedImageAlpha() {
  73 
  74         Color backgroundColor, extractedColor;
  75         // verify for all translucent buffered image types
  76         for (int type : translucentVariants) {
  77             // verify for both opaque and translucent background color
  78             for (int alpha : alphaValues) {
  79                 // create BufferedImage of dimension (50,50)
  80                 BufferedImage img = new
  81                     BufferedImage(width, height, type);
  82                 Graphics2D imgGraphics = (Graphics2D)img.getGraphics();
  83                 /* scale image to smaller dimension and set any
  84                  * background color with alpha.
  85                  */
  86                 backgroundColor = new Color(0, 255, 0, alpha);
  87                 imgGraphics.
  88                     drawImage(img, scaleX, scaleY, scaleWidth, scaleHeight,
  89                               backgroundColor, null);
  90                 imgGraphics.dispose();
  91 
  92                 /* get pixel information for background color with
  93                  * scaled coordinates.
  94                  */
  95                 extractedColor = new Color(img.getRGB(scaleX, scaleY), true);
  96                 verifyAlpha(extractedColor, alpha);
  97             }
  98         }
  99     }
 100 
 101     private static void validateVolatileImageAlpha() {
 102 
 103         Color backgroundColor, extractedColor;
 104         VolatileImage img;
 105         BufferedImage bufImg = new
 106                     BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
 107         for (int alpha : alphaValues) {
 108             backgroundColor = new Color(0, 255, 0, alpha);
 109             do {
 110                 img = createVolatileImage(width, height,
 111                                           Transparency.TRANSLUCENT);
 112                 Graphics2D imgGraphics = (Graphics2D)img.getGraphics();
 113                 // clear VolatileImage as by default it has white opaque image
 114                 imgGraphics.setComposite(AlphaComposite.Clear);
 115                 imgGraphics.fillRect(0,0, width, height);
 116 
 117                 imgGraphics.setComposite(AlphaComposite.SrcOver);
 118                 /* scale image to smaller dimension and set background color
 119                  * to green with translucent alpha.
 120                  */
 121                 imgGraphics.
 122                     drawImage(img, scaleX, scaleY, scaleWidth, scaleHeight,
 123                               backgroundColor, null);
 124                 //get BufferedImage out of VolatileImage
 125                 bufImg = img.getSnapshot();
 126                 imgGraphics.dispose();
 127             } while (img.contentsLost());
 128 
 129             /* get pixel information for background color with
 130              * scaled coordinates.
 131              */
 132             extractedColor = new Color(bufImg.getRGB(scaleX, scaleY), true);
 133             verifyAlpha(extractedColor, alpha);
 134         }
 135     }
 136 
 137     private static VolatileImage createVolatileImage(int width, int height,
 138                                                      int transparency) {
 139         GraphicsEnvironment ge = GraphicsEnvironment.
 140                                  getLocalGraphicsEnvironment();
 141         GraphicsConfiguration gc = ge.getDefaultScreenDevice().
 142                                    getDefaultConfiguration();
 143 
 144         VolatileImage image = gc.createCompatibleVolatileImage(width, height,
 145                                                                transparency);
 146         return image;
 147     }
 148 
 149     public static void main(String[] args) {
 150         // test alpha channel with different types of BufferedImage
 151         validateBufferedImageAlpha();
 152         // test alpha channel with VolatileImage
 153         validateVolatileImageAlpha();
 154     }
 155 }