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