1/*
2 * Copyright (c) 2007, 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
24import java.awt.Color;
25import java.awt.image.BufferedImage;
26
27public class ImageComparator {
28    double accuracy;
29    int errorCounter = 0;
30    double maxError = 0f;
31
32    int rMask = 0x00FF0000;
33    int gMask = 0x0000FF00;
34    int bMask = 0x000000FF;
35
36    int rShift = 16;
37    int gShift = 8;
38    int bShift = 0;
39
40    public ImageComparator() {
41        accuracy = 0;
42    }
43
44    public ImageComparator(double accuracy) {
45        this.accuracy = accuracy;
46    }
47
48    public ImageComparator(double accuracy, int rBits, int gBits, int bBits) {
49        this.accuracy = accuracy;
50        rShift += (8 - rBits);
51        gShift += (8 - gBits);
52        bShift += (8 - bBits);
53    }
54
55    public boolean compare(int c1, int c2) {
56        int d1 = Math.abs(((c1&bMask)>>bShift) - ((c2&bMask)>>bShift));
57        int d2 = Math.abs(((c1&gMask)>>gShift) - ((c2&gMask)>>gShift));
58        int d3 = Math.abs(((c1&rMask)>>rShift) - ((c2&rMask)>>rShift));
59        if (d1 < d2) d1 = d2;
60        if (d1 < d3) d1 = d3;
61        if (d1 >= accuracy) {
62            errorCounter++;
63            if (d1 > maxError) maxError = d1;
64            return false;
65        }
66        return true;
67    }
68
69    public boolean compare(double r1, double g1, double b1,
70                           double r2, double g2, double b2)
71    {
72        double d1 = Math.abs(r1 - r2);
73        double d2 = Math.abs(g1 - g2);
74        double d3 = Math.abs(b1 - b2);
75        if (d1 < d2) d1 = d2;
76        if (d1 < d3) d1 = d3;
77        if (d1 >= accuracy) {
78            errorCounter++;
79            if (d1 > maxError) maxError = d1;
80            return false;
81        }
82        return true;
83    }
84
85    public boolean compare(Color c1, Color c2) {
86        return compare(c1.getRed(), c1.getGreen(), c1.getBlue(),
87                       c2.getRed(), c2.getGreen(), c2.getBlue());
88    }
89
90    public boolean compare(BufferedImage img1, BufferedImage img2) {
91        boolean result = true;
92        if (img1.getWidth() != img2.getWidth() ||
93            img1.getHeight() != img2.getHeight()) {
94            throw new IllegalArgumentException(
95                "Images have different width or height");
96        }
97        for (int i = 0; i < img1.getWidth(); i++) {
98            for (int j = 0; j < img1.getHeight(); j++) {
99                boolean cmp = compare(img1.getRGB(i,j), img2.getRGB(i,j));
100                result = cmp && result;
101            }
102        }
103        return result;
104    }
105
106    public void resetStat() {
107        errorCounter = 0;
108        maxError = 0;
109    }
110
111    public String getStat() {
112        return "Accuracy " + accuracy + ". Errors " + errorCounter +
113               ". Max error " + maxError;
114    }
115
116    boolean compare(BufferedImage dst, BufferedImage gldImage, int x0, int y0,
117                    int dx, int dy)
118    {
119        int width = gldImage.getWidth();
120        int height = gldImage.getHeight();
121
122        if (x0 < 0) x0 = 0;
123        if (x0 > width - dx) x0 = width - dx;
124        if (y0 < 0) y0 = 0;
125        if (y0 > height - dy) y0 = height - dy;
126
127        int c = 0;
128
129        boolean result = true;
130        for (int i = x0; i < x0 + dx; i++) {
131            for (int j = y0; j < y0 + dy; j++) {
132                boolean cmp = compare(dst.getRGB(i-x0,j-y0),
133                                      gldImage.getRGB(i,j));
134                result = cmp && result;
135            }
136        }
137        return result;
138    }
139}
140