KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > test > util > ImageCompareTest


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.batik.test.util;
18
19 import java.awt.Color JavaDoc;
20 import java.awt.Graphics2D JavaDoc;
21 import java.awt.image.BufferedImage JavaDoc;
22 import java.awt.image.ColorModel JavaDoc;
23 import java.awt.image.RenderedImage JavaDoc;
24 import java.awt.image.WritableRaster JavaDoc;
25 import java.io.BufferedInputStream JavaDoc;
26 import java.io.File JavaDoc;
27 import java.io.FileOutputStream JavaDoc;
28 import java.io.IOException JavaDoc;
29 import java.io.InputStream JavaDoc;
30 import java.net.MalformedURLException JavaDoc;
31 import java.net.URL JavaDoc;
32
33 import org.apache.batik.ext.awt.image.GraphicsUtil;
34 import org.apache.batik.ext.awt.image.codec.PNGEncodeParam;
35 import org.apache.batik.ext.awt.image.codec.PNGImageEncoder;
36 import org.apache.batik.ext.awt.image.renderable.Filter;
37 import org.apache.batik.ext.awt.image.spi.ImageTagRegistry;
38 import org.apache.batik.test.AbstractTest;
39 import org.apache.batik.test.TestReport;
40 import org.apache.batik.util.ParsedURL;
41
42 /**
43  * This test does a pixel comparison of two images and passes if the
44  * two images are identical. It fails otherwise, producing a report
45  * describing why the two images are different.
46  *
47  * @author <a HREF="mailto:vhardy@apache.org">Vincent Hardy</a>
48  * @version $Id: ImageCompareTest.java,v 1.7 2005/04/01 02:28:16 deweese Exp $
49  */

50 public class ImageCompareTest extends AbstractTest {
51     public static final String JavaDoc ERROR_COULD_NOT_OPEN_IMAGE
52         = "ImageCompareTest.error.could.not.open.image";
53
54     public static final String JavaDoc ERROR_COULD_NOT_LOAD_IMAGE
55         = "ImageCompareTest.error.could.not.load.image";
56
57     public static final String JavaDoc ERROR_DIFFERENCES
58         = "ImageCompareTest.error.differences";
59
60     public static final String JavaDoc ERROR_WHILE_COMPARING_FILES
61         = "ImageCompareTest.error.while.comparing.files";
62
63     public static final String JavaDoc ENTRY_KEY_FIRST_IMAGE
64         = "ImageCompareTest.entry.key.first.image";
65
66     public static final String JavaDoc ENTRY_KEY_SECOND_IMAGE
67         = "ImageCompareTest.entry.key.second.image";
68
69     public static final String JavaDoc ENTRY_KEY_COMPARISON
70         = "ImageCompareTest.entry.key.comparison";
71     
72     public static final String JavaDoc ENTRY_KEY_DIFFERENCE
73         = "ImageCompareTest.entry.key.difference";
74
75     public static final String JavaDoc ENTRY_KEY_IMAGE_URL
76         = "ImageCompareTest.entry.key.image.url";
77
78     public static final String JavaDoc IMAGE_TYPE_DIFFERENCE
79         = "_diff";
80
81     public static final String JavaDoc IMAGE_TYPE_COMPARISON
82         = "_cmp";
83
84     /**
85      * Prefix for the temporary files created by Tests
86      * of this class
87      */

88     public static final String JavaDoc TEMP_FILE_PREFIX
89         = "ImageCompareTest";
90
91     /**
92      * Suffix for the temporary files created by
93      * Tests of this class
94      */

95     public static final String JavaDoc TEMP_FILE_SUFFIX
96         = "";
97
98     /**
99      * URL for the first image to be compared.
100      */

101     protected String JavaDoc urlAStr;
102     protected URL JavaDoc urlA;
103     
104     /**
105      * URL for the second image to be compared
106      */

107     protected String JavaDoc urlBStr;
108     protected URL JavaDoc urlB;
109
110     /**
111      * Resolves the input string as follows.
112      * + First, the string is interpreted as a file description.
113      * If the file exists, then the file name is turned into
114      * a URL.
115      * + Otherwise, the string is supposed to be a URL. If it
116      * is an invalid URL, an IllegalArgumentException is thrown.
117      */

118     protected URL JavaDoc resolveURL(String JavaDoc url){
119         // Is url a file?
120
File JavaDoc f = (new File JavaDoc(url)).getAbsoluteFile();
121         if(f.exists()){
122             try{
123                 return f.toURL();
124             }catch(MalformedURLException JavaDoc e){
125                 throw new IllegalArgumentException JavaDoc();
126             }
127         }
128         
129         // url is not a file. It must be a regular URL...
130
try{
131             return new URL JavaDoc(url);
132         }catch(MalformedURLException JavaDoc e){
133             throw new IllegalArgumentException JavaDoc(url);
134         }
135     }
136
137     /**
138      * This test makes a binary comparison of the two images
139      * (and not a pixel comparison). If the images are different,
140      * the test generates a report containing the two images and
141      * a delta images to help the user visualize the difference.
142      *
143      * @param urlA first image
144      * @param urlB second image
145      */

146     public ImageCompareTest(String JavaDoc urlA,
147                             String JavaDoc urlB){
148         urlAStr = urlA;
149         urlBStr = urlB;
150     }
151
152     protected void initURLs(){
153         if(urlA == null){
154             throw new IllegalArgumentException JavaDoc();
155         }
156         
157         if(urlB == null){
158             throw new IllegalArgumentException JavaDoc();
159         }
160
161         this.urlA = resolveURL(urlAStr);
162         this.urlB = resolveURL(urlBStr);
163     }
164
165     public TestReport rumImpl() throws Exception JavaDoc {
166         initURLs();
167
168         InputStream JavaDoc streamA = null;
169
170         try{
171             streamA = new BufferedInputStream JavaDoc(urlA.openStream());
172         }catch(IOException JavaDoc e){
173             return reportException(ERROR_COULD_NOT_OPEN_IMAGE, e);
174         }
175
176         InputStream JavaDoc streamB = null;
177
178         try{
179             streamB = new BufferedInputStream JavaDoc(urlB.openStream());
180         }catch(IOException JavaDoc e){
181             return reportException(ERROR_COULD_NOT_OPEN_IMAGE, e);
182         }
183
184         boolean accurate = false;
185
186         try{
187             accurate = compare(streamA, streamB);
188         }catch(IOException JavaDoc e){
189             TestReport report = reportException(ERROR_WHILE_COMPARING_FILES, e);
190             report.addDescriptionEntry(ENTRY_KEY_FIRST_IMAGE,
191                                        urlA.toString());
192             report.addDescriptionEntry(ENTRY_KEY_SECOND_IMAGE,
193                                        urlB.toString());
194             return report;
195         }
196
197         if(accurate){
198             return reportSuccess();
199         }
200
201         // We are in error (images are different: produce an image
202
// with the two images side by side as well as a diff image)
203
BufferedImage JavaDoc imageA = getImage(urlA);
204         if(imageA == null){
205             TestReport report = reportError(ERROR_COULD_NOT_LOAD_IMAGE);
206             report.addDescriptionEntry(ENTRY_KEY_IMAGE_URL,
207                                        urlA.toString());
208             return report;
209         }
210
211         BufferedImage JavaDoc imageB = getImage(urlB);
212         if(imageB == null){
213             TestReport report = reportError(ERROR_COULD_NOT_LOAD_IMAGE);
214             report.addDescriptionEntry(ENTRY_KEY_IMAGE_URL,
215                                        urlB.toString());
216             return report;
217         }
218
219         BufferedImage JavaDoc diff = buildDiffImage(imageA, imageB);
220         BufferedImage JavaDoc cmp = buildCompareImage(imageA, imageB);
221
222         File JavaDoc tmpDiff = imageToFile(diff, IMAGE_TYPE_DIFFERENCE);
223         File JavaDoc tmpCmp = imageToFile(cmp, IMAGE_TYPE_COMPARISON);
224
225         TestReport report = reportError(ERROR_DIFFERENCES);
226         report.addDescriptionEntry(ENTRY_KEY_COMPARISON, tmpCmp);
227         report.addDescriptionEntry(ENTRY_KEY_DIFFERENCE, tmpDiff);
228
229         return report;
230     }
231
232     protected BufferedImage JavaDoc buildCompareImage(BufferedImage JavaDoc ref,
233                                               BufferedImage JavaDoc gen){
234         BufferedImage JavaDoc cmp = new BufferedImage JavaDoc(ref.getWidth()*2,
235                                               ref.getHeight(),
236                                               BufferedImage.TYPE_INT_ARGB);
237
238         Graphics2D JavaDoc g = cmp.createGraphics();
239         g.setPaint(Color.white);
240         g.fillRect(0, 0, cmp.getWidth(), cmp.getHeight());
241         g.drawImage(ref, 0, 0, null);
242         g.translate(ref.getWidth(), 0);
243         g.drawImage(gen, 0, 0, null);
244         g.dispose();
245
246         return cmp;
247     }
248
249     /**
250      * Creates a temporary File into which the input image is
251      * saved.
252      */

253     protected File JavaDoc imageToFile(BufferedImage JavaDoc img,
254                                String JavaDoc imageType)
255         throws IOException JavaDoc {
256
257         File JavaDoc imageFile = makeRandomFileName(imageType);
258         imageFile.deleteOnExit();
259
260         PNGImageEncoder encoder
261             = new PNGImageEncoder(new FileOutputStream JavaDoc(imageFile),
262                                   PNGEncodeParam.getDefaultEncodeParam(img));
263         
264         encoder.encode(img);
265         
266         return imageFile;
267         
268     }
269
270     /**
271      * Creates a temporary File into which the input image is
272      * saved.
273      */

274     protected File JavaDoc makeRandomFileName(String JavaDoc imageType)
275         throws IOException JavaDoc {
276         
277         return File.createTempFile(TEMP_FILE_PREFIX,
278                                    TEMP_FILE_SUFFIX + imageType,
279                                    null);
280     }
281     
282     /**
283      * Builds a new BufferedImage that is the difference between the two input images
284      */

285     public static BufferedImage JavaDoc buildDiffImage(BufferedImage JavaDoc ref,
286                                                BufferedImage JavaDoc gen) {
287         BufferedImage JavaDoc diff = new BufferedImage JavaDoc(ref.getWidth(),
288                                                ref.getHeight(),
289                                                BufferedImage.TYPE_INT_ARGB);
290         WritableRaster JavaDoc refWR = ref.getRaster();
291         WritableRaster JavaDoc genWR = gen.getRaster();
292         WritableRaster JavaDoc dstWR = diff.getRaster();
293
294         boolean refPre = ref.isAlphaPremultiplied();
295         if (!refPre) {
296             ColorModel JavaDoc cm = ref.getColorModel();
297             cm = GraphicsUtil.coerceData(refWR, cm, true);
298             ref = new BufferedImage JavaDoc(cm, refWR, true, null);
299         }
300         boolean genPre = gen.isAlphaPremultiplied();
301         if (!genPre) {
302             ColorModel JavaDoc cm = gen.getColorModel();
303             cm = GraphicsUtil.coerceData(genWR, cm, true);
304             gen = new BufferedImage JavaDoc(cm, genWR, true, null);
305         }
306
307
308         int w=ref.getWidth();
309         int h=ref.getHeight();
310
311         int y, i,val;
312         int [] refPix = null;
313         int [] genPix = null;
314         for (y=0; y<h; y++) {
315             refPix = refWR.getPixels (0, y, w, 1, refPix);
316             genPix = genWR.getPixels (0, y, w, 1, genPix);
317             for (i=0; i<refPix.length; i++) {
318                 // val = ((genPix[i]-refPix[i])*5)+128;
319
val = ((refPix[i]-genPix[i])*10)+128;
320                 if ((val & 0xFFFFFF00) != 0)
321                     if ((val & 0x80000000) != 0) val = 0;
322                     else val = 255;
323                 genPix[i] = val;
324             }
325             dstWR.setPixels(0, y, w, 1, genPix);
326         }
327
328         if (!genPre) {
329             ColorModel JavaDoc cm = gen.getColorModel();
330             cm = GraphicsUtil.coerceData(genWR, cm, false);
331         }
332         
333         if (!refPre) {
334             ColorModel JavaDoc cm = ref.getColorModel();
335             cm = GraphicsUtil.coerceData(refWR, cm, false);
336         }
337
338         return diff;
339     }
340
341
342     /**
343      * Compare the two input streams
344      */

345     public static boolean compare(InputStream JavaDoc refStream,
346                                   InputStream JavaDoc newStream)
347         throws IOException JavaDoc{
348         int b, nb;
349         do {
350             b = refStream.read();
351             nb = newStream.read();
352         } while (b != -1 && nb != -1 && b == nb);
353         refStream.close();
354         newStream.close();
355         return (b == nb);
356     }
357
358     /**
359      * Loads an image from a URL
360      */

361     protected BufferedImage JavaDoc getImage(URL JavaDoc url) {
362         ImageTagRegistry reg = ImageTagRegistry.getRegistry();
363         Filter filt = reg.readURL(new ParsedURL(url));
364         if(filt == null){
365             return null;
366         }
367
368         RenderedImage JavaDoc red = filt.createDefaultRendering();
369         if(red == null){
370             return null;
371         }
372         
373         BufferedImage JavaDoc img = new BufferedImage JavaDoc(red.getWidth(),
374                                               red.getHeight(),
375                                               BufferedImage.TYPE_INT_ARGB);
376         red.copyData(img.getRaster());
377
378         return img;
379     }
380
381
382 }
383
384
Popular Tags