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 import java.awt.Color;
  25 import java.awt.Graphics2D;
  26 import java.awt.Image;
  27 import java.awt.Toolkit;
  28 import java.awt.image.BaseMultiResolutionImage;
  29 import java.awt.image.BufferedImage;
  30 import java.awt.image.CropImageFilter;
  31 import java.awt.image.FilteredImageSource;
  32 import java.awt.image.ImageFilter;
  33 import java.awt.image.ImageProducer;
  34 import java.awt.image.MultiResolutionImage;
  35 import java.awt.image.ReplicateScaleFilter;
  36 import java.util.HashSet;
  37 import java.util.Set;
  38 import java.util.List;
  39 
  40 /*
  41  * @test
  42  * @bug 8152309
  43  * @summary Seamless way of using image filters with multi-resolution images
  44  */
  45 public class ScaledFilterTest {
  46 
  47     private final static int IMAGE_SIZE = 500;
  48     private final static int X = 100;
  49     private final static int Y = 200;
  50     private final static int W = 300;
  51     private final static int H = 200;
  52     private final static int B = 10;
  53 
  54     private final static Color COLOR_BACKGROUND = Color.PINK;
  55     private final static Color COLOR_BORDER = Color.ORANGE;
  56     private final static Color COLOR_1X = Color.GREEN;
  57     private final static Color COLOR_2X = Color.BLUE;
  58 
  59     public static void main(String[] args) throws Exception {
  60 
  61         new CropFilterTest().test();
  62         new ReplicateScaleFilterTest().test();
  63     }
  64 
  65     static abstract class FilterTest {
  66 
  67         abstract ImageFilter createFilter();
  68 
  69         abstract void checkImage(Image image);
  70 
  71         void test() {
  72             Image image = getFilteredImage(getMRImage());
  73             checkImage(image);
  74         }
  75 
  76         Image getFilteredImage(Image image) {
  77             Toolkit toolkit = Toolkit.getDefaultToolkit();
  78             ImageProducer filteredImageSource = new FilteredImageSource(
  79                     image.getSource(), createFilter());
  80             return toolkit.createImage(filteredImageSource);
  81         }
  82 
  83         BufferedImage drawToBufferedImage(Image image, int scale) {
  84             int w = scale * IMAGE_SIZE;
  85             int h = scale * IMAGE_SIZE;
  86             BufferedImage buffImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
  87             Graphics2D g2d = buffImage.createGraphics();
  88             g2d.scale(scale, scale);
  89             g2d.drawImage(image, 0, 0, null);
  90             g2d.dispose();
  91             return buffImage;
  92         }
  93 
  94         Image getMRImage() {
  95             return new BaseMultiResolutionImage(
  96                     new BufferedImage[]{
  97                         generateImage(1, COLOR_1X),
  98                         generateImage(2, COLOR_2X)}
  99             );
 100         }
 101 
 102         BufferedImage generateImage(int scale, Color color) {
 103 
 104             int size = IMAGE_SIZE * scale;
 105             BufferedImage img = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB);
 106             Graphics2D g = img.createGraphics();
 107             g.scale(scale, scale);
 108             g.setColor(COLOR_BACKGROUND);
 109             g.fillRect(0, 0, IMAGE_SIZE, IMAGE_SIZE);
 110             g.setColor(COLOR_BORDER);
 111             g.fillRect(X, Y, W, H);
 112             g.setColor(color);
 113             g.fillRect(X + B, Y + B, W - 2 * B, H - 2 * B);
 114             g.dispose();
 115             return img;
 116         }
 117     }
 118 
 119     static class CropFilterTest extends FilterTest {
 120 
 121         @Override
 122         ImageFilter createFilter() {
 123             return new CropImageFilter(X, Y, W, H);
 124         }
 125 
 126         @Override
 127         void checkImage(Image image) {
 128             checkImage(drawToBufferedImage(image, 1), 1);
 129             checkImage(drawToBufferedImage(image, 2), 2);
 130         }
 131 
 132         void checkImage(BufferedImage buffImage, int scale) {
 133             int fw = scale * W;
 134             int fh = scale * H;
 135 
 136             Set<Integer> colors = new HashSet<>();
 137 
 138             for (int i = 0; i < fw; i++) {
 139                 colors.add(buffImage.getRGB(i, fh / 2));
 140             }
 141 
 142             checkColor(colors, scale);
 143             colors.clear();
 144 
 145             for (int i = 0; i < fh; i++) {
 146                 colors.add(buffImage.getRGB(fw / 2, i));
 147             }
 148 
 149             checkColor(colors, scale);
 150         }
 151 
 152         void checkColor(Set<Integer> colors, int scale) {
 153             if (colors.size() != 2) {
 154                 throw new RuntimeException("Wrong number of colors!");
 155             }
 156 
 157             if (!colors.contains(COLOR_BORDER.getRGB())) {
 158                 throw new RuntimeException("Color is not painted!");
 159             }
 160 
 161             Color testColor = scale == 1 ? COLOR_1X : COLOR_2X;
 162 
 163             if (!colors.contains(testColor.getRGB())) {
 164                 throw new RuntimeException("Color is not painted!");
 165             }
 166         }
 167     }
 168 
 169     static class ReplicateScaleFilterTest extends FilterTest {
 170 
 171         final int DST_WIDTH = IMAGE_SIZE / 2;
 172         final int DST_HEIGHT = IMAGE_SIZE / 3;
 173 
 174         @Override
 175         ImageFilter createFilter() {
 176             return new ReplicateScaleFilter(DST_WIDTH, DST_HEIGHT);
 177         }
 178 
 179         @Override
 180         void checkImage(Image image) {
 181 
 182             if (!(image instanceof MultiResolutionImage)) {
 183                 throw new RuntimeException("Not multi-resoltion image");
 184             }
 185 
 186             MultiResolutionImage mrImage = (MultiResolutionImage) image;
 187             List<Image> resoltionVariants = mrImage.getResolutionVariants();
 188 
 189             Image lowResolution = resoltionVariants.get(0);
 190             int w = lowResolution.getWidth(null);
 191             int h = lowResolution.getHeight(null);
 192 
 193             if (w != DST_WIDTH || h != DST_HEIGHT) {
 194                 throw new RuntimeException("Wrong low-resolution size!");
 195             }
 196 
 197             Image highResolution = resoltionVariants.get(1);
 198             w = highResolution.getWidth(null);
 199             h = highResolution.getHeight(null);
 200 
 201             if (w != 2 * DST_WIDTH || h != 2 * DST_HEIGHT) {
 202                 throw new RuntimeException("Wrong high-resolution size!");
 203             }
 204 
 205             BufferedImage buffImage = drawToBufferedImage(image, 1);
 206             int x = (X + W / 2) * DST_WIDTH / IMAGE_SIZE;
 207             int y = (Y + H / 2) * DST_HEIGHT / IMAGE_SIZE;
 208 
 209             if (buffImage.getRGB(x, y) != COLOR_1X.getRGB()) {
 210                 throw new RuntimeException("Wrong low-resolution color!");
 211             }
 212 
 213             buffImage = drawToBufferedImage(image, 2);
 214 
 215             if (buffImage.getRGB(2 * x, 2 * y) != COLOR_2X.getRGB()) {
 216                 throw new RuntimeException("Wrong high-resolution color!");
 217             }
 218         }
 219     }
 220 }