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 
24 import java.awt.Color;
25 import java.awt.image.BufferedImage;
26 
27 public 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 
ImageComparator()40     public ImageComparator() {
41         accuracy = 0;
42     }
43 
ImageComparator(double accuracy)44     public ImageComparator(double accuracy) {
45         this.accuracy = accuracy;
46     }
47 
ImageComparator(double accuracy, int rBits, int gBits, int bBits)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 
compare(int c1, int c2)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 
compare(double r1, double g1, double b1, double r2, double g2, double b2)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 
compare(Color c1, Color c2)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 
compare(BufferedImage img1, BufferedImage img2)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 
resetStat()106     public void resetStat() {
107         errorCounter = 0;
108         maxError = 0;
109     }
110 
getStat()111     public String getStat() {
112         return "Accuracy " + accuracy + ". Errors " + errorCounter +
113                ". Max error " + maxError;
114     }
115 
compare(BufferedImage dst, BufferedImage gldImage, int x0, int y0, int dx, int dy)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