e.g. Calendar Search Help
You must enter a value before pressing Search
batik

Class: org.apache.batik.test.util.ImageCompareTest   ©

 OK to copy?
001 /*
002 
003  ============================================================================
004                    The Apache Software License, Version 1.1
005  ============================================================================
006 
007  Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
008 
009  Redistribution and use in source and binary forms, with or without modifica-
010  tion, are permitted provided that the following conditions are met:
011 
012  1. Redistributions of  source code must  retain the above copyright  notice,
013     this list of conditions and the following disclaimer.
014 
015  2. Redistributions in binary form must reproduce the above copyright notice,
016     this list of conditions and the following disclaimer in the documentation
017     and/or other materials provided with the distribution.
018 
019  3. The end-user documentation included with the redistribution, if any, must
020     include  the following  acknowledgment:  "This product includes  software
021     developed  by the  Apache Software Foundation  (http://www.apache.org/)."
022     Alternately, this  acknowledgment may  appear in the software itself,  if
023     and wherever such third-party acknowledgments normally appear.
024 
025  4. The names "Batik" and  "Apache Software Foundation" must  not  be
026     used to  endorse or promote  products derived from  this software without
027     prior written permission. For written permission, please contact
028     apache@apache.org.
029 
030  5. Products  derived from this software may not  be called "Apache", nor may
031     "Apache" appear  in their name,  without prior written permission  of the
032     Apache Software Foundation.
033 
034  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
035  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
036  FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
037  APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
038  INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
039  DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
040  OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
041  ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
042  (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
043  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
044 
045  This software  consists of voluntary contributions made  by many individuals
046  on  behalf of the Apache Software  Foundation. For more  information on the
047  Apache Software Foundation, please see <http://www.apache.org/>.
048 
049 */
050 
051 package org.apache.batik.test.util;
052 
053 import java.awt.Color;
054 import java.awt.Graphics2D;
055 import java.awt.image.BufferedImage;
056 import java.awt.image.ColorModel;
057 import java.awt.image.RenderedImage;
058 import java.awt.image.WritableRaster;
059 import java.io.BufferedInputStream;
060 import java.io.File;
061 import java.io.FileOutputStream;
062 import java.io.IOException;
063 import java.io.InputStream;
064 import java.net.MalformedURLException;
065 import java.net.URL;
066 
067 import org.apache.batik.ext.awt.image.GraphicsUtil;
068 import org.apache.batik.ext.awt.image.codec.PNGEncodeParam;
069 import org.apache.batik.ext.awt.image.codec.PNGImageEncoder;
070 import org.apache.batik.ext.awt.image.renderable.Filter;
071 import org.apache.batik.ext.awt.image.spi.ImageTagRegistry;
072 import org.apache.batik.test.AbstractTest;
073 import org.apache.batik.test.TestReport;
074 import org.apache.batik.util.ParsedURL;
075 
076 /**
077  * This test does a pixel comparison of two images and passes if the 
078  * two images are identical. It fails otherwise, producing a report
079  * describing why the two images are different.
080  *
081  * @author <a href="vhardy@apache.org">Vincent Hardy</a>
082  * @version $Id: ImageCompareTest.java,v 1.5 2003/08/09 16:58:45 deweese Exp $
083  */
084 public class ImageCompareTest extends AbstractTest {
085     public static final String ERROR_COULD_NOT_OPEN_IMAGE
086         = "ImageCompareTest.error.could.not.open.image";
087 
088     public static final String ERROR_COULD_NOT_LOAD_IMAGE
089         = "ImageCompareTest.error.could.not.load.image";
090 
091     public static final String ERROR_DIFFERENCES
092         = "ImageCompareTest.error.differences";
093 
094     public static final String ERROR_WHILE_COMPARING_FILES
095         = "ImageCompareTest.error.while.comparing.files";
096 
097     public static final String ENTRY_KEY_FIRST_IMAGE
098         = "ImageCompareTest.entry.key.first.image";
099 
100     public static final String ENTRY_KEY_SECOND_IMAGE
101         = "ImageCompareTest.entry.key.second.image";
102 
103     public static final String ENTRY_KEY_COMPARISON
104         = "ImageCompareTest.entry.key.comparison";
105     
106     public static final String ENTRY_KEY_DIFFERENCE
107         = "ImageCompareTest.entry.key.difference";
108 
109     public static final String ENTRY_KEY_IMAGE_URL
110         = "ImageCompareTest.entry.key.image.url";
111 
112     public static final String IMAGE_TYPE_DIFFERENCE
113         = "_diff";
114 
115     public static final String IMAGE_TYPE_COMPARISON
116         = "_cmp";
117 
118     /**
119      * Prefix for the temporary files created by Tests
120      * of this class
121      */
122     public static final String TEMP_FILE_PREFIX 
123         = "ImageCompareTest";
124 
125     /**
126      * Suffix for the temporary files created by 
127      * Tests of this class
128      */
129     public static final String TEMP_FILE_SUFFIX
130         = "";
131 
132     /**
133      * URL for the first image to be compared.
134      */
135     protected String urlAStr;
136     protected URL urlA;
137     
138     /**
139      * URL for the second image to be compared
140      */
141     protected String urlBStr;
142     protected URL urlB;
143 
144     /**
145      * Resolves the input string as follows.
146      * + First, the string is interpreted as a file description.
147      *   If the file exists, then the file name is turned into
148      *   a URL.
149      * + Otherwise, the string is supposed to be a URL. If it
150      *   is an invalid URL, an IllegalArgumentException is thrown.
151      */
152     protected URL resolveURL(String url){
153         // Is url a file?
154         File f = (new File(url)).getAbsoluteFile();
155         if(f.exists()){
156             try{
157                 return f.toURL();
158             }catch(MalformedURLException e){
159                 throw new IllegalArgumentException();
160             }
161         }
162         
163         // url is not a file. It must be a regular URL...
164         try{
165             return new URL(url);
166         }catch(MalformedURLException e){
167             throw new IllegalArgumentException(url);
168         }
169     }
170 
171     /**
172      * This test makes a binary comparison of the two images
173      * (and not a pixel comparison). If the images are different,
174      * the test generates a report containing the two images and
175      * a delta images to help the user visualize the difference.
176      *
177      * @param urlA first image
178      * @param urlB second image
179      */
180     public ImageCompareTest(String urlA,
181                             String urlB){
182         urlAStr = urlA;
183         urlBStr = urlB;
184     }
185 
186     protected void initURLs(){
187         if(urlA == null){
188             throw new IllegalArgumentException();
189         }
190         
191         if(urlB == null){
192             throw new IllegalArgumentException();
193         }
194 
195         this.urlA = resolveURL(urlAStr);
196         this.urlB = resolveURL(urlBStr);
197     }
198 
199     public TestReport rumImpl() throws Exception {
200         initURLs();
201 
202         InputStream streamA = null;
203 
204         try{
205             streamA = new BufferedInputStream(urlA.openStream());
206         }catch(IOException e){
207             return reportException(ERROR_COULD_NOT_OPEN_IMAGE, e);
208         }
209 
210         InputStream streamB = null;
211 
212         try{
213             streamB = new BufferedInputStream(urlB.openStream());
214         }catch(IOException e){
215             return reportException(ERROR_COULD_NOT_OPEN_IMAGE, e);
216         }
217 
218         boolean accurate = false;
219 
220         try{
221             accurate = compare(streamA, streamB);
222         }catch(IOException e){
223             TestReport report = reportException(ERROR_WHILE_COMPARING_FILES, e);
224             report.addDescriptionEntry(ENTRY_KEY_FIRST_IMAGE,
225                                        urlA.toString());
226             report.addDescriptionEntry(ENTRY_KEY_SECOND_IMAGE,
227                                        urlB.toString());
228             return report;
229         }
230 
231         if(accurate){
232             return reportSuccess();
233         }
234 
235         // We are in error (images are different: produce an image
236         // with the two images side by side as well as a diff image)
237         BufferedImage imageA = getImage(urlA);
238         if(imageA == null){
239             TestReport report = reportError(ERROR_COULD_NOT_LOAD_IMAGE);
240             report.addDescriptionEntry(ENTRY_KEY_IMAGE_URL,
241                                        urlA.toString());
242             return report;
243         }
244 
245         BufferedImage imageB = getImage(urlB);
246         if(imageB == null){
247             TestReport report = reportError(ERROR_COULD_NOT_LOAD_IMAGE);
248             report.addDescriptionEntry(ENTRY_KEY_IMAGE_URL,
249                                        urlB.toString());
250             return report;
251         }
252 
253         BufferedImage diff = buildDiffImage(imageA, imageB);
254         BufferedImage cmp  = buildCompareImage(imageA, imageB);
255 
256         File tmpDiff = imageToFile(diff, IMAGE_TYPE_DIFFERENCE);
257         File tmpCmp  = imageToFile(cmp,  IMAGE_TYPE_COMPARISON);
258 
259         TestReport report = reportError(ERROR_DIFFERENCES);
260         report.addDescriptionEntry(ENTRY_KEY_COMPARISON, tmpCmp);
261         report.addDescriptionEntry(ENTRY_KEY_DIFFERENCE, tmpDiff);
262 
263         return report;
264     }
265 
266     protected BufferedImage buildCompareImage(BufferedImage ref,
267                                               BufferedImage gen){
268         BufferedImage cmp = new BufferedImage(ref.getWidth()*2,
269                                               ref.getHeight(),
270                                               BufferedImage.TYPE_INT_ARGB);
271 
272         Graphics2D g = cmp.createGraphics();
273         g.setPaint(Color.white);
274         g.fillRect(0, 0, cmp.getWidth(), cmp.getHeight());
275         g.drawImage(ref, 0, 0, null);
276         g.translate(ref.getWidth(), 0);
277         g.drawImage(gen, 0, 0, null);
278         g.dispose();
279 
280         return cmp;
281     }
282 
283     /**
284      * Creates a temporary File into which the input image is
285      * saved.
286      */
287     protected File imageToFile(BufferedImage img,
288                                String imageType)
289         throws IOException {
290 
291         File imageFile =  makeRandomFileName(imageType);
292         imageFile.deleteOnExit();
293 
294         PNGImageEncoder encoder 
295             = new PNGImageEncoder(new FileOutputStream(imageFile),
296                                   PNGEncodeParam.getDefaultEncodeParam(img));
297         
298         encoder.encode(img);
299         
300         return imageFile;
301         
302     }
303 
304     /**
305      * Creates a temporary File into which the input image is
306      * saved.
307      */
308     protected File makeRandomFileName(String imageType)
309         throws IOException {
310         
311         return File.createTempFile(TEMP_FILE_PREFIX,
312                                    TEMP_FILE_SUFFIX + imageType,
313                                    null);
314     }
315     
316     /**
317      * Builds a new BufferedImage that is the difference between the two input images
318      */
319     public static BufferedImage buildDiffImage(BufferedImage ref,
320                                                BufferedImage gen) {
321         BufferedImage diff = new BufferedImage(ref.getWidth(),
322                                                ref.getHeight(),
323                                                BufferedImage.TYPE_INT_ARGB);
324         WritableRaster refWR = ref.getRaster();
325         WritableRaster genWR = gen.getRaster();
326         WritableRaster dstWR = diff.getRaster();
327 
328         boolean refPre = ref.isAlphaPremultiplied();
329         if (!refPre) {
330             ColorModel     cm = ref.getColorModel();
331             cm = GraphicsUtil.coerceData(refWR, cm, true);
332             ref = new BufferedImage(cm, refWR, true, null);
333         }
334         boolean genPre = gen.isAlphaPremultiplied();
335         if (!genPre) {
336             ColorModel     cm = gen.getColorModel();
337             cm = GraphicsUtil.coerceData(genWR, cm, true);
338             gen = new BufferedImage(cm, genWR, true, null);
339         }
340 
341 
342         int w=ref.getWidth();
343         int h=ref.getHeight();
344 
345         int y, i,val;
346         int [] refPix = null;
347         int [] genPix = null;
348         for (y=0; y<h; y++) {
349             refPix = refWR.getPixels  (0, y, w, 1, refPix);
350             genPix = genWR.getPixels  (0, y, w, 1, genPix);
351             for (i=0; i<refPix.length; i++) {
352                 // val = ((genPix[i]-refPix[i])*5)+128;
353                 val = ((refPix[i]-genPix[i])*10)+128;
354                 if ((val & 0xFFFFFF00) != 0)
355                     if ((val & 0x80000000) != 0) val = 0;
356                     else                         val = 255;
357                 genPix[i] = val;
358             }
359             dstWR.setPixels(0, y, w, 1, genPix);
360         }
361 
362         if (!genPre) {
363             ColorModel cm = gen.getColorModel();
364             cm = GraphicsUtil.coerceData(genWR, cm, false);
365         }
366         
367         if (!refPre) {
368             ColorModel cm = ref.getColorModel();
369             cm = GraphicsUtil.coerceData(refWR, cm, false);
370         }
371 
372         return diff;
373     }
374 
375 
376     /**
377      * Compare the two input streams
378      */
379     public static boolean compare(InputStream refStream,
380                                   InputStream newStream)
381         throws IOException{
382         int b, nb;
383         do {
384             b = refStream.read();
385             nb = newStream.read();
386         } while (b != -1 && nb != -1 && b == nb);
Rate387         refStream.close();
Rate388         newStream.close();
389         return (b == nb);
390     }
391 
392     /**
393      * Loads an image from a URL
394      */
395     protected BufferedImage getImage(URL url) {
396         ImageTagRegistry reg = ImageTagRegistry.getRegistry();
397         Filter filt = reg.readURL(new ParsedURL(url));
398         if(filt == null){
399             return null;
400         }
401 
402         RenderedImage red = filt.createDefaultRendering();
403         if(red == null){
404             return null;
405         }
406         
407         BufferedImage img = new BufferedImage(red.getWidth(),
408                                               red.getHeight(),
409                                               BufferedImage.TYPE_INT_ARGB);
410         red.copyData(img.getRaster());
411 
412         return img;
413     }
414 
415 
416 }


            
All Examples in File:
Example
Line
Rating (found
useful by...)
387 0% of 0
388 0% of 0