001: package abbot.tester;
002:
003: import java.awt.Image;
004: import java.awt.image.*;
005: import java.io.*;
006: import javax.swing.ImageIcon;
007:
008: import abbot.Log;
009:
010: import com.sun.image.codec.jpeg.*;
011:
012: /**
013: This code expects the availability of the com.sun.image.codec.jpeg
014: extensions from the Sun JDK 1.3 or JRE.
015:
016: Original comparison code contributed by asmithmb.
017:
018: author: asmithmontebello@aol.com, twall
019: */
020: public class ImageComparator implements java.util.Comparator {
021:
022: public static String IMAGE_SUFFIX;
023:
024: static {
025: // TODO: figure out how to do PNG stuff under 1.3 (w/o ImageIO)
026: try {
027: Class.forName("javax.imageio.ImageIO");
028: IMAGE_SUFFIX = ".png";
029: } catch (ClassNotFoundException e) {
030: IMAGE_SUFFIX = ".jpg";
031: }
032: }
033:
034: private static Image convertToImage(Object obj) throws IOException {
035: if (obj instanceof String) {
036: obj = new File((String) obj);
037: }
038: if (obj instanceof BufferedImage) {
039: // Convert to file and back to avoid unexplained
040: // memory-only BufferedImage differences
041: File tmp = File.createTempFile("ImageComparator",
042: IMAGE_SUFFIX);
043: tmp.deleteOnExit();
044: writeImage(tmp, (BufferedImage) obj);
045: obj = tmp;
046: }
047: if (obj instanceof File) {
048: obj = new ImageIcon(((File) obj).toURI().toURL())
049: .getImage();
050: }
051: if (obj instanceof Image) {
052: return (Image) obj;
053: }
054: return null;
055: }
056:
057: public static void writeImage(File file, BufferedImage img)
058: throws IOException {
059: if (".png".equals(IMAGE_SUFFIX))
060: writePNG(file, img);
061: else
062: writeJPEG(file, img);
063: }
064:
065: public static void writePNG(File file, BufferedImage img)
066: throws IOException {
067: javax.imageio.ImageIO.write(img, "png", file);
068: }
069:
070: /** Write the given buffered image to disk. */
071: public static void writeJPEG(File file, BufferedImage img)
072: throws IOException {
073: FileOutputStream os = new FileOutputStream(file);
074: JPEGImageEncoder ie = JPEGCodec.createJPEGEncoder(os);
075: JPEGEncodeParam param = ie.getDefaultJPEGEncodeParam(img);
076: // Lossless, please
077: param.setQuality(1.0f, false);
078: ie.setJPEGEncodeParam(param);
079: ie.encode(img);
080: os.close();
081: }
082:
083: /**
084: Compare two images. May be BufferedImages or File arguments.
085: */
086: public int compare(Object obj1, Object obj2) {
087: try {
088: obj1 = convertToImage(obj1);
089: } catch (IOException io) {
090: throw new IllegalArgumentException(
091: "Object is not convertable to an Image: " + obj1);
092: }
093: try {
094: obj2 = convertToImage(obj2);
095: } catch (IOException io) {
096: throw new IllegalArgumentException(
097: "Object is not convertable to an Image: " + obj2);
098: }
099: Log.debug("Comparing " + obj1 + " and " + obj2);
100: Image image1 = (Image) obj1;
101: int w = image1.getWidth(null);
102: int h = image1.getHeight(null);
103: Image image2 = (Image) obj2;
104: int w2 = image2.getWidth(null);
105: int h2 = image2.getHeight(null);
106: if (w * h != w2 * h2) {
107: return w * h - w2 * h2;
108: }
109: int[] pixels1 = new int[w * h];
110: int[] pixels2 = new int[w * h];
111: PixelGrabber pg1 = new PixelGrabber(image1, 0, 0, w, h,
112: pixels1, 0, w);
113: PixelGrabber pg2 = new PixelGrabber(image2, 0, 0, w, h,
114: pixels2, 0, w);
115: try {
116: pg1.grabPixels();
117: pg2.grabPixels();
118: for (int i = 0; i < w * h; i++) {
119: if (pixels1[i] != pixels2[i]) {
120: return pixels1[i] - pixels2[i];
121: }
122: }
123: } catch (InterruptedException e) {
124: }
125: return 0;
126: }
127:
128: /** Comparators are equal if they're the same class. */
129: public boolean equals(Object obj) {
130: return obj == this
131: || (obj != null && obj.getClass().equals(getClass()));
132: }
133: }
|