You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-dev@xmlgraphics.apache.org by vh...@apache.org on 2001/02/15 03:27:30 UTC

cvs commit: xml-batik/sources/org/apache/batik/util SoftReferenceCache.java

vhardy      01/02/14 18:27:30

  Modified:    sources/org/apache/batik/bridge CSSUtilities.java
                        SVGColorProfileElementBridge.java
                        SVGImageElementBridge.java
                        SVGPatternElementBridge.java
               sources/org/apache/batik/ext/awt/color ICCColorSpaceExt.java
               sources/org/apache/batik/ext/awt/image/renderable
                        RasterRable.java URLImageCache.java
               sources/org/apache/batik/ext/awt/image/rendered
                        ProfileRed.java
               sources/org/apache/batik/svggen
                        ImageHandlerBase64Encoder.java
  Added:       sources/org/apache/batik/ext/awt/color
                        NamedProfileCache.java
               sources/org/apache/batik/util SoftReferenceCache.java
  Log:
  More work on color-profile:
  
  a. Added caching for color-profile so that if the same color-profile is
     referenced multiple times, it is only loaded once.
  
  b. Added color-profile support on Base64 images.
  
  c. Abstracted Thomas' URLImageCache into a SoftReferenceCache (in xx.util)
     that URLImageCache and NamedProfileCache (new) extend by offering
     strongly typed methods.
  
  The modifications are validated by a new test: samples\tests\colorProfile.svg.
  
  Revision  Changes    Path
  1.15      +1 -11     xml-batik/sources/org/apache/batik/bridge/CSSUtilities.java
  
  Index: CSSUtilities.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/CSSUtilities.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- CSSUtilities.java	2001/02/14 20:34:19	1.14
  +++ CSSUtilities.java	2001/02/15 02:27:28	1.15
  @@ -70,7 +70,7 @@
    * A collection of utility methods involving CSS.
    *
    * @author <a href="mailto:stephane@hillion.org">Stephane Hillion</a>
  - * @version $Id: CSSUtilities.java,v 1.14 2001/02/14 20:34:19 vhardy Exp $
  + * @version $Id: CSSUtilities.java,v 1.15 2001/02/15 02:27:28 vhardy Exp $
    */
   public class CSSUtilities implements SVGConstants {
   
  @@ -643,18 +643,8 @@
               return null;
           }
   
  -        for(int i=0; i<colorValue.length; i++){
  -            System.out.println("colorValue[" + i + "] = " + colorValue[i]);
  -            // colorValue[i] /= 255f;
  -        }
  -
  -        System.out.println("opacity : " + opacity);
  -
           // Convert values to RGB
           float rgb[] = profileCS.intendedToRGB(colorValue);
  -        for(int i=0; i<colorValue.length; i++){
  -            System.out.println("rgb[" + i + "] = " + rgb[i]);
  -        }
   
           return new Color(rgb[0], rgb[1], rgb[2], opacity);
       }
  
  
  
  1.2       +28 -3     xml-batik/sources/org/apache/batik/bridge/SVGColorProfileElementBridge.java
  
  Index: SVGColorProfileElementBridge.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/SVGColorProfileElementBridge.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- SVGColorProfileElementBridge.java	2001/02/14 20:34:20	1.1
  +++ SVGColorProfileElementBridge.java	2001/02/15 02:27:28	1.2
  @@ -20,6 +20,7 @@
   import org.apache.batik.bridge.resources.Messages;
   import org.apache.batik.dom.svg.SVGOMDocument;
   import org.apache.batik.ext.awt.color.ICCColorSpaceExt;
  +import org.apache.batik.ext.awt.color.NamedProfileCache;
   
   import org.w3c.dom.Document;
   import org.w3c.dom.Element;
  @@ -31,10 +32,15 @@
    * an <tt>ICC_ColorSpace</tt> object.
    *
    * @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
  - * @version $Id: SVGColorProfileElementBridge.java,v 1.1 2001/02/14 20:34:20 vhardy Exp $
  + * @version $Id: SVGColorProfileElementBridge.java,v 1.2 2001/02/15 02:27:28 vhardy Exp $
    */
   public class SVGColorProfileElementBridge implements Bridge, SVGConstants {
       /**
  +     * Profile cache
  +     */
  +    public NamedProfileCache cache = new NamedProfileCache();
  +
  +    /**
        * Builds an ICC_ColorSpace for the given input color profile 
        * name, if the name can be resolved and successfully accessed
        *
  @@ -49,9 +55,17 @@
       public ICCColorSpaceExt build(String iccProfileName,
                                     BridgeContext ctx,
                                     Element paintedElement){
  -        System.out.println("Invoking ColorProfileElementBridge : " + iccProfileName);
  +        /*
  +         * Check if there is one if the cache.
  +         */
  +        ICCColorSpaceExt cs = cache.request(iccProfileName);
  +        if(cs != null){
  +            return cs;
  +        }
   
           /**
  +         * There was no cached copies for the profile. Load it
  +         * now.
            * Search for a color-profile element with specific name
            */
           Document doc = paintedElement.getOwnerDocument();
  @@ -106,8 +120,15 @@
            */
           String intentStr = profile.getAttributeNS(null, SVG_RENDERING_INTENT_ATTRIBUTE);
           int intent = convertIntent(intentStr);
  +
  +        cs = new ICCColorSpaceExt(p, intent);
   
  -        return new ICCColorSpaceExt(p, intent);
  +        /**
  +         * Add profile to cache
  +         */
  +        cache.put(iccProfileName, cs);
  +
  +        return cs;
       }
   
       private int convertIntent(String intentStr){
  @@ -125,6 +146,10 @@
           }
           if(VALUE_RENDERING_INTENT_ABSOLUTE_COLORIMETRIC_VALUE.equals(intentStr)){
               return ICCColorSpaceExt.ABSOLUTE_COLORIMETRIC;
  +        }
  +
  +        if(VALUE_RENDERING_INTENT_SATURATION_VALUE.equals(intentStr)){
  +            return ICCColorSpaceExt.SATURATION;
           }
   
           throw new IllegalAttributeValueException
  
  
  
  1.10      +1 -4      xml-batik/sources/org/apache/batik/bridge/SVGImageElementBridge.java
  
  Index: SVGImageElementBridge.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/SVGImageElementBridge.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- SVGImageElementBridge.java	2001/02/14 20:34:21	1.9
  +++ SVGImageElementBridge.java	2001/02/15 02:27:28	1.10
  @@ -66,7 +66,7 @@
    *
    * @author <a href="mailto:Thierry.Kormann@sophia.inria.fr">Thierry Kormann</a>
    * @author <a href="mailto:Thomas.DeWeeese@Kodak.com">Thomas DeWeese</a>
  - * @version $Id: SVGImageElementBridge.java,v 1.9 2001/02/14 20:34:21 vhardy Exp $
  + * @version $Id: SVGImageElementBridge.java,v 1.10 2001/02/15 02:27:28 vhardy Exp $
    */
   public class SVGImageElementBridge implements GraphicsNodeBridge,
                                                 SVGConstants {
  @@ -200,8 +200,6 @@
           String colorProfileProperty 
               = svgElement.getAttributeNS(null, CSS_COLOR_PROFILE_PROPERTY);
   
  -        System.out.println(CSS_COLOR_PROFILE_PROPERTY + " : " + colorProfileProperty);
  -
           /**
            * The only cases that need special handling are
            * 'sRGB' and 'name'
  @@ -229,7 +227,6 @@
                       = profileBridge.build(colorProfileProperty,
                                             ctx, svgElement);
   
  -                System.out.println("colorSpace : " + colorSpace);
               }
           }
                 
  
  
  
  1.12      +1 -2      xml-batik/sources/org/apache/batik/bridge/SVGPatternElementBridge.java
  
  Index: SVGPatternElementBridge.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/SVGPatternElementBridge.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- SVGPatternElementBridge.java	2001/02/14 20:34:22	1.11
  +++ SVGPatternElementBridge.java	2001/02/15 02:27:28	1.12
  @@ -47,7 +47,7 @@
    * a <tt>PatternPaint</tt>
    *
    * @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
  - * @version $Id: SVGPatternElementBridge.java,v 1.11 2001/02/14 20:34:22 vhardy Exp $
  + * @version $Id: SVGPatternElementBridge.java,v 1.12 2001/02/15 02:27:28 vhardy Exp $
    */
   public class SVGPatternElementBridge implements PaintBridge, SVGConstants {
   
  @@ -296,7 +296,6 @@
           CSSPrimitiveValue v =
               (CSSPrimitiveValue)paintedCssDecl.getPropertyCSSValue(paintOpacityProperty);
           float opacity = CSSUtilities.convertOpacity(v);
  -        System.out.println("Pattern on " + paintOpacityProperty + " = " + opacity);
           if(opacity != 1){
               float[][] matrix = {{1, 0, 0, 0, 0},
                                   {0, 1, 0, 0, 0},
  
  
  
  1.2       +16 -8     xml-batik/sources/org/apache/batik/ext/awt/color/ICCColorSpaceExt.java
  
  Index: ICCColorSpaceExt.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/ext/awt/color/ICCColorSpaceExt.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ICCColorSpaceExt.java	2001/02/14 20:34:26	1.1
  +++ ICCColorSpaceExt.java	2001/02/15 02:27:28	1.2
  @@ -19,7 +19,7 @@
    * relative colorimetric.
    *
    * @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
  - * @version $Id: ICCColorSpaceExt.java,v 1.1 2001/02/14 20:34:26 vhardy Exp $
  + * @version $Id: ICCColorSpaceExt.java,v 1.2 2001/02/15 02:27:28 vhardy Exp $
    */
   public class ICCColorSpaceExt extends ICC_ColorSpace {
       public static final int PERCEPTUAL = 0;
  @@ -41,10 +41,18 @@
           case ABSOLUTE_COLORIMETRIC:
           case SATURATION:
           case PERCEPTUAL:
  -            return;
  +            break;
           default:
               throw new IllegalArgumentException();
           }
  +
  +        /**
  +         * Apply the requested intent into the profile
  +         */
  +        if(intent != AUTO){
  +            byte[] hdr = p.getData(ICC_Profile.icSigHead);
  +            hdr[ICC_Profile.icHdrRenderingIntent] = (byte)intent;
  +        }
       }
   
       /**
  @@ -73,7 +81,6 @@
        * base class's toRGB method
        */
       public float[] perceptualToRGB(float[] values){
  -        System.out.println("==> perceptual");
           return toRGB(values);
       }
   
  @@ -82,22 +89,23 @@
        * conversion
        */
       public float[] relativeColorimetricToRGB(float[] values){
  -        System.out.println("==> relativeColorimetric");
           float[] ciexyz = toCIEXYZ(values);
           return sRGB.fromCIEXYZ(ciexyz);
       }
   
       /**
  -     * Absolute colorimetric. NOT IMPLEMENTED
  +     * Absolute colorimetric. NOT IMPLEMENTED.
  +     * Temporarily returns same as perceptual
        */
       public float[] absoluteColorimetricToRGB(float[] values){
  -        throw new Error();
  +        return perceptualToRGB(values);
       }
   
       /**
  -     * Saturation. NOT IMPLEMENTED
  +     * Saturation. NOT IMPLEMENTED. Temporarily returns same
  +     * as perceptual.
        */
       public float[] saturationToRGB(float[] values){
  -        throw new Error();
  +        return perceptualToRGB(values);
       }
   }
  
  
  
  1.1                  xml-batik/sources/org/apache/batik/ext/awt/color/NamedProfileCache.java
  
  Index: NamedProfileCache.java
  ===================================================================
  /*****************************************************************************
   * Copyright (C) The Apache Software Foundation. All rights reserved.        *
   * ------------------------------------------------------------------------- *
   * This software is published under the terms of the Apache Software License *
   * version 1.1, a copy of which has been included with this distribution in  *
   * the LICENSE file.                                                         *
   *****************************************************************************/
  
  package org.apache.batik.ext.awt.color;
  
  import java.awt.image.RenderedImage;
  
  import java.net.URL;
  
  import java.util.Map;
  import java.util.HashMap;
  
  import java.lang.ref.SoftReference;
  
  import org.apache.batik.util.SoftReferenceCache;
  
  /**
   * This class manages a cache of soft references to named profiles that
   * we have already loaded. 
   *
   * @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
   * @version $Id: NamedProfileCache.java,v 1.1 2001/02/15 02:27:28 vhardy Exp $
   */
  
  public class NamedProfileCache extends SoftReferenceCache{
  
      static NamedProfileCache theCache = new NamedProfileCache();
  
      public static NamedProfileCache getDefaultCache() { return theCache; }
  
      /**
       * Let people create there own caches.
       */
      public NamedProfileCache() { }
  
      /**
       * Check if <tt>request(profileName)</tt> will return with a ICCColorSpaceExt
       * (not putting you on the hook for it).  Note that it is possible
       * that this will return true but between this call and the call
       * to request the soft-reference will be cleared.  So it
       * is still possible for request to return NULL, just much less
       * likely (you can always call 'clear' in that case). 
       */
      public synchronized boolean isPresent(String profileName) {
          return super.isPresentImpl(profileName);
      }
  
      /**
       * Check if <tt>request(profileName)</tt> will return immediately with the
       * ICCColorSpaceExt.  Note that it is possible that this will return
       * true but between this call and the call to request the
       * soft-reference will be cleared.
       */
      public synchronized boolean isDone(String profileName) {
          return super.isDoneImpl(profileName);
      }
  
      /**
       * If this returns null then you are now 'on the hook'.
       * to put the ICCColorSpaceExt associated with String into the
       * cache.  */
      public synchronized ICCColorSpaceExt request(String profileName) {
          return (ICCColorSpaceExt)super.requestImpl(profileName);
      }
  
      /**
       * Clear the entry for String.
       * This is the easiest way to 'get off the hook'.
       * if you didn't indend to get on it.
       */
      public synchronized void clear(String profileName) {
          super.clearImpl(profileName);
      }
  
      /**
       * Associate bi with profileName.  bi is only referenced through
       * a soft reference so don't rely on the cache to keep it
       * around.  If the map no longer contains our profileName it was
       * probably cleared or flushed since we were put on the hook
       * for it, so in that case we will do nothing.
       */
      public synchronized void put(String profileName, ICCColorSpaceExt bi) {
          super.putImpl(profileName, bi);
      }
  }
  
  
  
  1.5       +11 -4     xml-batik/sources/org/apache/batik/ext/awt/image/renderable/RasterRable.java
  
  Index: RasterRable.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/ext/awt/image/renderable/RasterRable.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- RasterRable.java	2001/02/14 20:34:26	1.4
  +++ RasterRable.java	2001/02/15 02:27:29	1.5
  @@ -21,7 +21,6 @@
   import java.awt.Graphics2D;
   import java.awt.Label;
   import java.awt.MediaTracker;
  -import java.awt.MediaTracker;
   import java.awt.Point;
   import java.awt.Rectangle;
   import java.awt.RenderingHints;
  @@ -64,7 +63,7 @@
    * RenderableImage world.
    *
    * @author <a href="mailto:Thomas.DeWeese@Kodak.com>Thomas DeWeese</a>
  - * @version $Id: RasterRable.java,v 1.4 2001/02/14 20:34:26 vhardy Exp $
  + * @version $Id: RasterRable.java,v 1.5 2001/02/15 02:27:29 vhardy Exp $
    */
   public class RasterRable
       extends    AbstractRable {
  @@ -205,7 +204,6 @@
            */
           public ImageLoader(ICCColorSpaceExt colorSpace) { 
               this.colorSpace = colorSpace;
  -            System.out.println("colorSpace : " + colorSpace);
           }
   
           /**
  @@ -371,7 +369,6 @@
               RenderedImage bi = cache.request(url);
   
               if (bi == null){
  -                System.out.println("Loading " + url);
                   // Image is not loaded yet
                   bi = super.load();
                   
  @@ -451,5 +448,15 @@
                   return null;
               }
           }
  +
  +        public RenderedImage load() {
  +            RenderedImage ri = super.load();
  +            if(ri != null && colorSpace != null){
  +                ri = applyColorProfile(ri);
  +            }
  +
  +            return ri;
  +        }
  +
       }
   }
  
  
  
  1.4       +8 -79     xml-batik/sources/org/apache/batik/ext/awt/image/renderable/URLImageCache.java
  
  Index: URLImageCache.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/ext/awt/image/renderable/URLImageCache.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- URLImageCache.java	2001/02/14 20:34:27	1.3
  +++ URLImageCache.java	2001/02/15 02:27:29	1.4
  @@ -17,6 +17,8 @@
   
   import java.lang.ref.SoftReference;
   
  +import org.apache.batik.util.SoftReferenceCache;
  +
   /**
    * This class manages a cache of soft references to Images that
    * we have already loaded.  Adding an image is two fold.
  @@ -28,12 +30,10 @@
    * been put they will be blocked until the put.
    */
   
  -public class URLImageCache {
  +public class URLImageCache extends SoftReferenceCache{
   
       static URLImageCache theCache = new URLImageCache();
   
  -    HashMap map = new HashMap();
  -
       public static URLImageCache getDefaultCache() { return theCache; }
   
       /**
  @@ -41,18 +41,6 @@
        */
       public URLImageCache() { }
   
  -
  -    /**
  -     * Let people flush the cache (remove any cached data).  Pending
  -     * requests will be treated as though clear() was called on the
  -     * URL, this should cause them to go and re-read the data.  
  -     */
  -
  -    public synchronized void flush() {
  -        map.clear();
  -        this.notifyAll();
  -    }
  -
       /**
        * Check if <tt>request(url)</tt> will return with a RenderedImage
        * (not putting you on the hook for it).  Note that it is possible
  @@ -62,24 +50,7 @@
        * likely (you can always call 'clear' in that case). 
        */
       public synchronized boolean isPresent(URL url) {
  -        if (!map.containsKey(url))
  -            return false;
  -
  -        Object o = map.get(url);
  -        if (o == null)  
  -            // It's been requested but hasn't been 'put' yet.
  -            return true;
  -
  -        // It's been put let's make sure the soft reference hasn't
  -        // been cleared.
  -        SoftReference sr = (SoftReference)o;
  -        o = sr.get();
  -        if (o != null)
  -            return true;
  -
  -        // Soft reference was cleared, so remove our record of url.
  -        clear(url);
  -        return false;
  +        return super.isPresentImpl(url);
       }
   
       /**
  @@ -89,16 +60,7 @@
        * soft-reference will be cleared.
        */
       public synchronized boolean isDone(URL url) {
  -        Object o = map.get(url);
  -        if (o == null) return false;
  -        SoftReference sr = (SoftReference)o;
  -        o = sr.get();
  -        if (o != null)
  -            return true;
  -
  -        // Soft reference was cleared
  -        clear(url);
  -        return false;
  +        return super.isDoneImpl(url);
       }
   
       /**
  @@ -106,35 +68,7 @@
        * to put the RenderedImage associated with URL into the
        * cache.  */
       public synchronized RenderedImage request(URL url) {
  -        if (map.containsKey(url)) {
  -
  -            Object o = map.get(url);
  -            while(o == null) {
  -                try {
  -                    // When something is cleared or put we will be notified.
  -                    wait();
  -                }
  -                catch (InterruptedException ie) { }
  -
  -                // check if url was cleared, if so it will most likely
  -                // never be 'put'.
  -                if (!map.containsKey(url))
  -                    break;
  -
  -                // Let's see if it was put...
  -                o = map.get(url);
  -            }
  -            if (o != null) {
  -                SoftReference sr = (SoftReference)o;
  -                o = sr.get();
  -                if (o != null)
  -                    return (RenderedImage)o;
  -            }
  -        }
  -
  -        // So now the caller get's the hot potato.
  -        map.put(url, null);
  -        return null;
  +        return (RenderedImage)super.requestImpl(url);
       }
   
       /**
  @@ -143,8 +77,7 @@
        * if you didn't indend to get on it.
        */
       public synchronized void clear(URL url) {
  -        map.remove(url);
  -        this.notifyAll();
  +        super.clearImpl(url);
       }
   
       /**
  @@ -155,10 +88,6 @@
        * for it, so in that case we will do nothing.
        */
       public synchronized void put(URL url, RenderedImage bi) {
  -        if (map.containsKey(url)) {
  -            SoftReference ref = new SoftReference(bi);
  -            map.put(url, ref);
  -            this.notifyAll();
  -        }
  +        super.putImpl(url, bi);
       }
   }
  
  
  
  1.2       +1 -2      xml-batik/sources/org/apache/batik/ext/awt/image/rendered/ProfileRed.java
  
  Index: ProfileRed.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/ext/awt/image/rendered/ProfileRed.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ProfileRed.java	2001/02/14 20:34:28	1.1
  +++ ProfileRed.java	2001/02/15 02:27:29	1.2
  @@ -37,7 +37,7 @@
    * on its source
    *
    * @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
  - * @version $Id: ProfileRed.java,v 1.1 2001/02/14 20:34:28 vhardy Exp $
  + * @version $Id: ProfileRed.java,v 1.2 2001/02/15 02:27:29 vhardy Exp $
    */
   public class ProfileRed extends AbstractRed {
       private static final ColorSpace sRGBCS 
  @@ -102,7 +102,6 @@
        * any bug as of JDK 1.3.
        */
       public WritableRaster copyData(WritableRaster argbWR){
  -        System.err.println("Applying color profile .....");
           try{
               RenderedImage img = getSource();
   
  
  
  
  1.7       +37 -8     xml-batik/sources/org/apache/batik/svggen/ImageHandlerBase64Encoder.java
  
  Index: ImageHandlerBase64Encoder.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/svggen/ImageHandlerBase64Encoder.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- ImageHandlerBase64Encoder.java	2001/02/06 12:33:38	1.6
  +++ ImageHandlerBase64Encoder.java	2001/02/15 02:27:29	1.7
  @@ -29,7 +29,7 @@
    * the data protocol.
    *
    * @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
  - * @version $Id: ImageHandlerBase64Encoder.java,v 1.6 2001/02/06 12:33:38 tkormann Exp $
  + * @version $Id: ImageHandlerBase64Encoder.java,v 1.7 2001/02/15 02:27:29 vhardy Exp $
    * @see             org.apache.batik.svggen.SVGGraphics2D
    * @see             org.apache.batik.svggen.ImageHandler
    */
  @@ -151,13 +151,41 @@
       /**
        * Unit testing
        */
  +    public static final String USAGE = "java org.apache.batik.svggen.ImageHandlerBase64Encoder [<imageFile>]";
  +
       public static void main(String args[]) {
  -        BufferedImage buf = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
  -        Graphics2D g = buf.createGraphics();
  -        g.setPaint(Color.red);
  -        g.fillRect(0, 0, 50, 50);
  -        g.fillRect(50, 50, 50, 50);
  -        g.dispose();
  +        BufferedImage buf = null;
  +
  +        if(args.length == 0){
  +            buf = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
  +            Graphics2D g = buf.createGraphics();
  +            g.setPaint(Color.red);
  +            g.fillRect(0, 0, 50, 50);
  +            g.fillRect(50, 50, 50, 50);
  +            g.dispose();
  +        }
  +        else{
  +            Component cmp = new Component(){};
  +            MediaTracker mediaTracker = new MediaTracker(cmp);
  +            Image img = Toolkit.getDefaultToolkit().createImage(args[0]);
  +            mediaTracker.addImage(img, 0);
  +            try{
  +                mediaTracker.waitForAll();
  +            }catch(InterruptedException e){
  +                img = null;
  +            }
  +
  +            if(img == null){
  +                System.err.println("Could not load : " + args[0]);
  +            }
  +
  +            buf = new BufferedImage(img.getWidth(null),
  +                                    img.getHeight(null),
  +                                    BufferedImage.TYPE_INT_ARGB);
  +            Graphics2D g = buf.createGraphics();
  +            g.drawImage(img, 0, 0, null);
  +            g.dispose();
  +        }
   
           ImageHandler imageHandler = new ImageHandlerBase64Encoder();
           Document domFactory = TestUtil.getDocumentPrototype();
  @@ -171,7 +199,8 @@
           System.out.println();
           System.out.println("<svg width=\"450\" height=\"500\">");
           System.out.println("    <rect width=\"100%\" height=\"100%\" fill=\"yellow\" />");
  -        System.out.println("    <image x=\"30\" y=\"30\" xlink:href=\"" + imageElement.getAttributeNS(null, SVGSyntax.ATTR_XLINK_HREF) + "\" width=\"100\" height=\"100\" />");
  +        System.out.println("    <image width=\"" + buf.getWidth() + "\" height=\"" +
  +                           buf.getHeight() + "\" xlink:href=\"" + XLinkSupport.getXLinkHref(imageElement) + "\" />");
           System.out.println("</svg>");
           System.exit(0);
       }
  
  
  
  1.1                  xml-batik/sources/org/apache/batik/util/SoftReferenceCache.java
  
  Index: SoftReferenceCache.java
  ===================================================================
  /*****************************************************************************
   * Copyright (C) The Apache Software Foundation. All rights reserved.        *
   * ------------------------------------------------------------------------- *
   * This software is published under the terms of the Apache Software License *
   * version 1.1, a copy of which has been included with this distribution in  *
   * the LICENSE file.                                                         *
   *****************************************************************************/
  
  package org.apache.batik.util;
  
  import java.util.Map;
  import java.util.HashMap;
  
  import java.lang.ref.SoftReference;
  
  /**
   * This class manages a cache of soft references to objects that may
   * take some time to load or create, such as images loaded from the 
   * network.
   *
   * Adding an object is two fold: <br />
   * + First you add the key, this lets the cache know that someone is
   *   working on that key.  <br />
   * + Then when the completed object is ready you put it into the cache.<P>
   *
   * If someone requests a key after it has been added but before it has
   * been put they will be blocked until the put.
   */
  
  public class SoftReferenceCache {
      HashMap map = new HashMap();
  
      /**
       * Let people create there own caches.
       */
      protected SoftReferenceCache() { }
  
  
      /**
       * Let people flush the cache (remove any cached data).  Pending
       * requests will be treated as though clear() was called on the
       * key, this should cause them to go and re-read the data.  
       */
      public synchronized void flush() {
          map.clear();
          this.notifyAll();
      }
  
      /**
       * Check if <tt>request(key)</tt> will return with an Object
       * (not putting you on the hook for it).  Note that it is possible
       * that this will return true but between this call and the call
       * to request the soft-reference will be cleared.  So it
       * is still possible for request to return NULL, just much less
       * likely (you can always call 'clear' in that case). 
       */
      protected final synchronized boolean isPresentImpl(Object key) {
          if (!map.containsKey(key))
              return false;
  
          Object o = map.get(key);
          if (o == null)  
              // It's been requested but hasn't been 'put' yet.
              return true;
  
          // It's been put let's make sure the soft reference hasn't
          // been cleared.
          SoftReference sr = (SoftReference)o;
          o = sr.get();
          if (o != null)
              return true;
  
          // Soft reference was cleared, so remove our record of key.
          clearImpl(key);
          return false;
      }
  
      /**
       * Check if <tt>request(key)</tt> will return immediately with the
       * Object.  Note that it is possible that this will return
       * true but between this call and the call to request the
       * soft-reference will be cleared.
       */
      protected final synchronized boolean isDoneImpl(Object key) {
          Object o = map.get(key);
          if (o == null) return false;
          SoftReference sr = (SoftReference)o;
          o = sr.get();
          if (o != null)
              return true;
  
          // Soft reference was cleared
          clearImpl(key);
          return false;
      }
  
      /**
       * If this returns null then you are now 'on the hook'.
       * to put the Object associated with key into the
       * cache.  */
      protected final synchronized Object requestImpl(Object key) {
          if (map.containsKey(key)) {
  
              Object o = map.get(key);
              while(o == null) {
                  try {
                      // When something is cleared or put we will be notified.
                      wait();
                  }
                  catch (InterruptedException ie) { }
  
                  // check if key was cleared, if so it will most likely
                  // never be 'put'.
                  if (!map.containsKey(key))
                      break;
  
                  // Let's see if it was put...
                  o = map.get(key);
              }
              if (o != null) {
                  SoftReference sr = (SoftReference)o;
                  o = sr.get();
                  if (o != null)
                      return o;
              }
          }
  
          // So now the caller get's the hot potato.
          map.put(key, null);
          return null;
      }
  
      /**
       * Clear the entry for key.
       * This is the easiest way to 'get off the hook'.
       * if you didn't indend to get on it.
       */
      protected final synchronized void clearImpl(Object key) {
          map.remove(key);
          this.notifyAll();
      }
  
      /**
       * Associate object with key.  'object' is only referenced through
       * a soft reference so don't rely on the cache to keep it
       * around.  If the map no longer contains our url it was
       * probably cleared or flushed since we were put on the hook
       * for it, so in that case we will do nothing.
       */
      protected final synchronized void putImpl(Object key, Object object) {
          if (map.containsKey(key)) {
              SoftReference ref = new SoftReference(object);
              map.put(key, ref);
              this.notifyAll();
          }
      }
  }