1/*
2 * Copyright (c) 1997, 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 */
23package org.netbeans.jemmy.image;
24
25import java.awt.image.BufferedImage;
26
27/**
28 * Compares two images with color mapping defined by {@code ColorModel}
29 * implementation.
30 *
31 * @author Alexandre Iline (alexandre.iline@oracle.com)
32 */
33public class ColorImageComparator extends StrictImageComparator {
34
35    ColorMap leftMap, rightMap;
36    ImageComparator comparator = null;
37
38    /**
39     * Creates a comparator with a color maps. Object created by this
40     * constructor behaves like {@code StrictImageComparator}. Object
41     * created works faster because it does not create intermediate images for
42     * another comparator.
43     *
44     * @param map Map applied to both left and right images during comparision.
45     */
46    public ColorImageComparator(ColorMap map) {
47        leftMap = map;
48        rightMap = map;
49    }
50
51    /**
52     * Creates a comparator with {@code map} color mapping. Actual
53     * comparision perfomed by {@code comparator} parameter.
54     *
55     * @param map Map applied to both left and right images during comparision.
56     * @param subComparator comporator to perform a comparision of to images
57     * with mapped colors.
58     */
59    public ColorImageComparator(ColorMap map, ImageComparator subComparator) {
60        this(map);
61        this.comparator = subComparator;
62    }
63
64    /**
65     * Creates a comparator with two color maps. Object created by this
66     * constructor behaves like {@code StrictImageComparator}. Object
67     * created works faster because it does not create intermediate images for
68     * another comparator.
69     *
70     * @param leftMap Map applied to the left image during comparision.
71     * @param rightMap Map applied to the right image during comparision.
72     */
73    public ColorImageComparator(ColorMap leftMap, ColorMap rightMap) {
74        this.leftMap = leftMap;
75        this.rightMap = rightMap;
76    }
77
78    /**
79     * Creates a comparator with two color maps. Actual comparision perfomed by
80     * {@code comparator} parameter.
81     *
82     * @param leftMap Map applied to the left image during comparision.
83     * @param rightMap Map applied to the right image during comparision.
84     * @param subComparator comporator to perform a comparision of to images
85     * with mapped colors.
86     */
87    public ColorImageComparator(ColorMap leftMap, ColorMap rightMap, ImageComparator subComparator) {
88        this(leftMap, rightMap);
89        this.comparator = subComparator;
90    }
91
92    /**
93     * Compares images by {@code ImageComparator} passed into constructor,
94     * or itself if no {@code ImageComparator} was passed, processing both
95     * images by {@code ColorMap} instance before comparision.
96     */
97    @Override
98    public boolean compare(BufferedImage image1, BufferedImage image2) {
99        if (comparator != null) {
100            return comparator.compare(recolor(image1, leftMap), recolor(image2, rightMap));
101        } else {
102            return super.compare(image1, image2);
103        }
104    }
105
106    private BufferedImage recolor(BufferedImage src, ColorMap map) {
107        BufferedImage result = new BufferedImage(src.getWidth(), src.getHeight(), src.getType());
108        for (int x = 0; x < src.getWidth(); x++) {
109            for (int y = 0; y < src.getWidth(); y++) {
110                result.setRGB(x, y, map.mapColor(src.getRGB(x, y)));
111            }
112        }
113        return result;
114    }
115
116    @Override
117    protected final boolean compareColors(int rgb1, int rgb2) {
118        return leftMap.mapColor(rgb1) == rightMap.mapColor(rgb2);
119    }
120
121    /**
122     * Interface to map colors during the comparision.
123     */
124    public static interface ColorMap {
125
126        /**
127         * Maps one color into another.
128         *
129         * @param rgb an original color.
130         * @return a converted color.
131         */
132        public int mapColor(int rgb);
133    }
134
135    /**
136     * Turns {@code foreground} color to white, other - to black.
137     */
138    public static class ForegroundColorMap implements ColorMap {
139
140        int foreground;
141
142        /**
143         * Constructs a ColorImageComparator$ForegroundColorMap object.
144         *
145         * @param foreground Foreground color.
146         */
147        public ForegroundColorMap(int foreground) {
148            this.foreground = foreground;
149        }
150
151        @Override
152        public int mapColor(int rgb) {
153            return (rgb == foreground) ? 0xffffff : 0;
154        }
155    }
156
157    /**
158     * Turns {@code background} color to black, left others unchanged.
159     */
160    public static class BackgroundColorMap implements ColorMap {
161
162        int background;
163
164        /**
165         * Constructs a ColorImageComparator$BackgroundColorMap object.
166         *
167         * @param background Background color.
168         */
169        public BackgroundColorMap(int background) {
170            this.background = background;
171        }
172
173        @Override
174        public int mapColor(int rgb) {
175            return (rgb == background) ? 0 : rgb;
176        }
177    }
178
179}
180