You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-users@xmlgraphics.apache.org by "Johnson, Jonathan" <jj...@454.com> on 2006/01/18 22:55:48 UTC

How to load an SVG resource into a java.awt.Image?

Swing has a simple utility method to load a gif, jpeg or png file 

 

Image Toolkit.getDefaultToolkit().getImage(url)

 

and place it in a java.awt.Image object.  At this point you can create a
swing JButton and hand it the Image.

 

Using Batik I'm looking for a way to load a svg into a java.awt.Image,
Icon, BufferedImage or into some object that I can convert to an
java.awt.Image.  While preserving the transparent background as well.

 

Using a JSVGComponent is not the right solution since a JButton accepts
an Icon and not a component for attaching a common button image.  I also
want to avoid transcoding the svg to a png file.

 

Is there a Batik API call to achieve this?

 

All I could find is this relatively complex solution...

 

String parser = XMLResourceDescriptor.getXMLParserClassName();

SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser);

 

File file = new File(MyClass.class.getResource("test.svg").getFile());

document = (SVGDocument) f.createDocument(file.toURL().toString());

 

// Build the tree and get the document dimensions

UserAgentAdapter userAgentAdapter = new UserAgentAdapter();

BridgeContext bridgeContext = new BridgeContext(userAgentAdapter);

GVTBuilder builder = new GVTBuilder();

GraphicsNode graphicsNode = builder.build(bridgeContext, document);

 

BufferedImage bufferedImage = new BufferedImage((int)(bounds.getWidth()
* scaleX), (int) (bounds.getHeight() * scaleY),
BufferedImage.TYPE_INT_RGB);

Graphics2D g2d = (Graphics2D) bufferedImage.getGraphics();

graphicsNode.paint(g2d);

g2d.dispose();

 

return bufferedImage;

 


LEGAL NOTICE:
Unless expressly stated otherwise, this message is confidential and may be privileged. It is intended for the addressee(s) only. Access to this e-mail by anyone else is unauthorized. If you are not an addressee, any disclosure or copying of the contents or any action taken (or not taken) in reliance on it is unauthorized and may be unlawful. If you are not an addressee, please inform the sender immediately.



Re: How to load an SVG resource into a java.awt.Image?

Posted by Svenskmand <sv...@gmail.com>.
In case anyone other than me had the same problem here is my solution :), in
short it is a class to make a java.awt.Image from a svg file given by a
java.net.URL or a org.w3c.dom.svg.SVGDocument.

tags: java.awt.BufferedImage Batik Swing

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package javarummikub;

import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.GVTBuilder;
import org.apache.batik.bridge.UserAgentAdapter;
import org.apache.batik.dom.svg.SAXSVGDocumentFactory;
import org.apache.batik.gvt.GraphicsNode;
import org.apache.batik.util.XMLResourceDescriptor;
import org.w3c.dom.Element;
import org.w3c.dom.svg.SVGDocument;

import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import org.apache.batik.ext.awt.RenderingHintsKeyExt;

/**
 * Immutable class to get the Image representation of a svg resource.
 */
public final class SvgImage {

    /** Root node of svg document */
    private final GraphicsNode rootSvgNode;
    /** Loaded SVG document */
    private final SVGDocument svgDocument;

    /**
     * Load the svg resource from a URL into a document.
     * @param url location of svg resource.
     * @throws java.io.IOException when svg resource cannot be read.
     */
    public SvgImage(URL url) throws IOException {
        String parser = XMLResourceDescriptor.getXMLParserClassName();
        SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(parser);
        svgDocument =
                (SVGDocument) factory.createDocument(url.toString());
        rootSvgNode = getRootNode(svgDocument);
    }

    /**
     * Load the svg from a document.
     *
     * @param document svg resource
     */
    public SvgImage(SVGDocument document) {
        svgDocument = document;
        rootSvgNode = getRootNode(svgDocument);
    }

    /**
     * Get svg root from the given document.
     *
     * @param document svg resource
     */
    private static GraphicsNode getRootNode(SVGDocument document) {
        // Build the tree and get the document dimensions
        UserAgentAdapter userAgentAdapter = new UserAgentAdapter();
        BridgeContext bridgeContext = new BridgeContext(userAgentAdapter);
        GVTBuilder builder = new GVTBuilder();

        return builder.build(bridgeContext, document);
    }

    /**
     * Get the svg root node of the document.
     *
     * @return svg root node.
     */
    public GraphicsNode getRootSvgNode() {
        return rootSvgNode;
    }

    /**
     * Get the svg document.
     * @return the svg document.
     */
    public SVGDocument getSvgDocument() {
        return svgDocument;
    }

    /**
     * Renders and returns the svg based image.
     *
     * @param width desired width, if it is less than or equal to 0 aspect
     * ratio is preserved and the size is determined by height.
     * @param height desired height, if it is less than or equal to 0 aspect
     * ratio is preserved and the size is determined by width.
     * @return image of the rendered svg.'
     * TODO: modify to also give a image that preserves aspects but matches
     *       width or height individually.
     */
    public Image getImage(int width, int height) {
        /* Adjusts the scale of the transformation below, if either width or
         * height is less than or equal to 0 the aspect ratio is preserved.
*/
        Element elt = svgDocument.getRootElement();
        Rectangle2D bounds = rootSvgNode.getPrimitiveBounds();
        double scaleX, scaleY;
        if(width <= 0){
            scaleX = scaleY = height/bounds.getHeight();
            width = (int) (scaleX * bounds.getWidth());
        }else if(height <= 0){
            scaleX = scaleY = width/bounds.getWidth();
            height = (int) (scaleY * bounds.getHeight());
        }else{
            scaleX = width/bounds.getWidth();
            scaleY = height/bounds.getHeight();
        }
        
        // Paint svg into image buffer
        BufferedImage bufferedImage = new BufferedImage(width,
                height, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = (Graphics2D) bufferedImage.getGraphics();

        // For a smooth graphic with no jagged edges or rastorized look.
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        
        g2d.setRenderingHint(RenderingHintsKeyExt.KEY_TRANSCODING,
                RenderingHintsKeyExt.VALUE_TRANSCODING_PRINTING);

        // Scale image to desired size
        AffineTransform usr2dev =
                new AffineTransform(scaleX, 0.0, 0.0, scaleY, 0.0, 0.0);
        g2d.transform(usr2dev);
        rootSvgNode.paint(g2d);

        // Cleanup and return image
        g2d.dispose();
        return bufferedImage;
    }
}
-- 
View this message in context: http://www.nabble.com/How-to-load-an-SVG-resource-into-a-java.awt.Image--tp2457141p18477049.html
Sent from the Batik - Users mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: batik-users-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: batik-users-help@xmlgraphics.apache.org


Re: How to load an SVG resource into a java.awt.Image?

Posted by Svenskmand <sv...@gmail.com>.

Helder Magalhães wrote:
> 
> There's a recent thread [1] which may help. Search for:
> 
> BridgeContext bc = c.getUpdateManager().getBridgeContext();
> 

the problem is i have this class

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package javarummikub;

import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.GVTBuilder;
import org.apache.batik.bridge.UserAgentAdapter;
import org.apache.batik.bridge.ViewBox;
import org.apache.batik.dom.svg.SAXSVGDocumentFactory;
import org.apache.batik.gvt.GraphicsNode;
import org.apache.batik.util.XMLResourceDescriptor;
import org.w3c.dom.Element;
import org.w3c.dom.svg.SVGDocument;

import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import org.apache.batik.ext.awt.RenderingHintsKeyExt;

/**
 * Immutable class to get the Image representation of a svg resource.
 */
public final class SvgImage {

    /** Root node of svg document */
    private final GraphicsNode rootSvgNode;
    /** Loaded SVG document */
    private final SVGDocument svgDocument;

    /**
     * Load the svg resource from a URL into a document.
     * @param url location of svg resource.
     * @throws java.io.IOException when svg resource cannot be read.
     */
    public SvgImage(URL url) throws IOException {
        String parser = XMLResourceDescriptor.getXMLParserClassName();
        SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(parser);
        svgDocument =
                (SVGDocument) factory.createDocument(url.toString());
        rootSvgNode = getRootNode(svgDocument);
    }

    /**
     * Load the svg from a document.
     *
     * @param document svg resource
     */
    public SvgImage(SVGDocument document) {
        svgDocument = document;
        rootSvgNode = getRootNode(svgDocument);
    }

    /**
     * Get svg root from the given document.
     *
     * @param document svg resource
     */
    private GraphicsNode getRootNode(SVGDocument document) {
        // Build the tree and get the document dimensions
        UserAgentAdapter userAgentAdapter = new UserAgentAdapter();
        BridgeContext bridgeContext = new BridgeContext(userAgentAdapter);
        GVTBuilder builder = new GVTBuilder();

        return builder.build(bridgeContext, document);
    }

    /**
     * Get the svg root node of the document.
     *
     * @return svg root node.
     */
    public GraphicsNode getRootSvgNode() {
        return rootSvgNode;
    }

    /**
     * Get the svg document.
     * @return the svg document.
     */
    public SVGDocument getSvgDocument() {
        return svgDocument;
    }

    /**
     * Renders and returns the svg based image.
     *
     * @param width desired width
     * @param height desired height
     * @return image of the rendered svg.
     */
    public Image getImage(int width, int height) {
        // Paint svg into image buffer
        BufferedImage bufferedImage = new BufferedImage(width,
                height, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = (Graphics2D) bufferedImage.getGraphics();

        // For a smooth graphic with no jagged edges or rastorized look.
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        
        g2d.setRenderingHint(RenderingHintsKeyExt.KEY_TRANSCODING,
                RenderingHintsKeyExt.VALUE_TRANSCODING_PRINTING);

        // Scale image to desired size
        Element elt = svgDocument.getRootElement();
        AffineTransform usr2dev = ViewBox.getViewTransform(null, elt, width,
height, null);
        //                                                                                 
Problem is here ^
        g2d.transform(usr2dev);

        rootSvgNode.paint(g2d);

        // Cleanup and return image
        g2d.dispose();
        return bufferedImage;
    }
}

and there is only a SVGDocument and a GraphicsNode, where from neither i can
get the BridgeContext (as far as i can see, from the javadoc and 
http://www.yworks.com/products/yDoc/showcase/batik-1.5/index.html this
javadoc for SVG  ). The above code displays the svg-file, but the resizeing
doesn't work, the AffineTransform returned is just the
identitytransformation:

[1 0 0]
[0 1 0]

so the svg doesn't resize at all. Any hints where to get the BridgeContext
from this code would be very much appreciated :)

PS: also if i change the line:

AffineTransform usr2dev = ViewBox.getViewTransform(null, elt, width, height,
null);

to the two new lines:

UserAgentAdapter userAgentAdapter = new UserAgentAdapter();
AffineTransform usr2dev = ViewBox.getViewTransform(null, elt, width,
                              height, new BridgeContext(userAgentAdapter));

it also just returns the identitytransformation :S

Regards


-- 
View this message in context: http://www.nabble.com/How-to-load-an-SVG-resource-into-a-java.awt.Image--tp2457141p18475618.html
Sent from the Batik - Users mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: batik-users-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: batik-users-help@xmlgraphics.apache.org


Re: How to load an SVG resource into a java.awt.Image?

Posted by Helder Magalhães <he...@gmail.com>.
> i get at compile error marked with the arrow /* >>> */
> because there is missing a BridgeContext, but i don't know where to get it
> from :S

There's a recent thread [1] which may help. Search for:

BridgeContext bc = c.getUpdateManager().getBridgeContext();

Hope this helps,

 Helder Magalhães

[1] http://mail-archives.apache.org/mod_mbox/xmlgraphics-batik-users/200807.mbox/%3cOFAB2C09FA.6842A2EC-ON85257486.0038A543-85257486.0038FA31@knotes.kodak.com%3e

---------------------------------------------------------------------
To unsubscribe, e-mail: batik-users-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: batik-users-help@xmlgraphics.apache.org


RE: How to load an SVG resource into a java.awt.Image?

Posted by Svenskmand <sv...@gmail.com>.
Anybody knows if this class ever made it into Batik and if so under what
name?, if not then is there anybody that knows how to fix it so it works
with Batik 1.7, i get at compile error marked with the arrow /* >>> */
because there is missing a BridgeContext, but i don't know where to get it
from :S


Jon Johnson wrote:
> 
> Usages: java.awt.Image image = new SvgImage(url).getImage(50, 50);
>         java.awt.Image image = new SvgImage(doc).getImage(50, 50);
> 
> Code:
> 
> import org.apache.batik.bridge.BridgeContext;
> import org.apache.batik.bridge.GVTBuilder;
> import org.apache.batik.bridge.UserAgentAdapter;
> import org.apache.batik.bridge.ViewBox;
> import org.apache.batik.dom.svg.SAXSVGDocumentFactory;
> import org.apache.batik.gvt.GraphicsNode;
> import org.apache.batik.util.XMLResourceDescriptor;
> import org.w3c.dom.Element;
> import org.w3c.dom.svg.SVGDocument;
> 
> import java.awt.*;
> import java.awt.geom.AffineTransform;
> import java.awt.image.BufferedImage;
> import java.io.IOException;
> import java.net.URL;
> 
> /**
>  * Immutable class to get the Image representation of a svg resource.
>  */
> public final class SvgImage
> {
>     /** Root node of svg document */
>     private final GraphicsNode rootSvgNode;
> 
>     /** Loaded SVG document */
>     private final SVGDocument svgDocument;
> 
>     /**
>      * Load the svg resource from a URL into a document.
>      * @param url location of svg resource.
>      * @throws java.io.IOException when svg resource cannot be read.
>      */
>     public SvgImage(URL url)
>         throws IOException
>     {
>         String parser = XMLResourceDescriptor.getXMLParserClassName();
>         SAXSVGDocumentFactory factory = new
> SAXSVGDocumentFactory(parser);
>         svgDocument =
> (SVGDocument)factory.createDocument(url.toString());
>         rootSvgNode = getRootNode(svgDocument);
>     }
> 
>     /**
>      * Load the svg from a document.
>      *
>      * @param document svg resource
>      */
>     public SvgImage(SVGDocument document)
>     {
>         svgDocument = document;
>         rootSvgNode = getRootNode(svgDocument);
>     }
> 
>     /**
>      * Get svg root from the given document.
>      *
>      * @param document svg resource
>      */
>     private static GraphicsNode getRootNode(SVGDocument document)
>     {
>         // Build the tree and get the document dimensions
>         UserAgentAdapter userAgentAdapter = new UserAgentAdapter();
>         BridgeContext bridgeContext = new
> BridgeContext(userAgentAdapter);
>         GVTBuilder builder = new GVTBuilder();
> 
>         return builder.build(bridgeContext, document);
>     }
> 
>     /**
>      * Get the svg root node of the document.
>      *
>      * @return svg root node.
>      */
>     public GraphicsNode getRootSvgNode()
>     {
>         return rootSvgNode;
>     }
> 
>     /**
>      * Get the svg document.
>      * @return the svg document.
>      */
>     public SVGDocument getSvgDocument()
>     {
>         return svgDocument;
>     }
> 
>     /**
>      * Renders and returns the svg based image.
>      *
>      * @param width desired width
>      * @param height desired height
>      * @return image of the rendered svg.
>      */
>     public Image getImage(int width, int height)
>     {
>         // Paint svg into image buffer
>         BufferedImage bufferedImage = new BufferedImage(width,
>             height, BufferedImage.TYPE_INT_ARGB);
>         Graphics2D g2d = (Graphics2D) bufferedImage.getGraphics();
> 
>         // For a smooth graphic with no jagged edges or rastorized look.
>         g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
>             RenderingHints.VALUE_ANTIALIAS_ON);
>         g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
>             RenderingHints.VALUE_INTERPOLATION_BILINEAR);
> 
>         // Scale image to desired size
>         Element elt = svgDocument.getRootElement();
>         /* >>> */AffineTransform usr2dev = ViewBox.getViewTransform(null,
> elt, width, height);
>         g2d.transform(usr2dev);
> 
>         rootSvgNode.paint(g2d);
> 
>         // Cleanup and return image
>         g2d.dispose();
>         return bufferedImage;
>     }
> }
> 

-- 
View this message in context: http://www.nabble.com/How-to-load-an-SVG-resource-into-a-java.awt.Image--tp2457141p18455900.html
Sent from the Batik - Users mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: batik-users-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: batik-users-help@xmlgraphics.apache.org


Re: How to load an SVG resource into a java.awt.Image?

Posted by th...@kodak.com.
Hi Johnson,

"Johnson, Jonathan" <jj...@454.com> wrote on 01/18/2006 04:55:48 PM:

> Swing has a simple utility method to load a gif, jpeg or png file 
> 
> Image Toolkit.getDefaultToolkit().getImage(url)
> 
> and place it in a java.awt.Image object.  At this point you can create a 
swing
> JButton and hand it the Image.
> 
> Using Batik I’m looking for a way to load a svg into a java.awt.Image, 
Icon, 
> BufferedImage or into some object that I can convert to an 
java.awt.Image. 
> While preserving the transparent background as well.

> Using a JSVGComponent is not the right solution since a JButton accepts 
an 
> Icon and not a component for attaching a common button image.  I also 
want to 
> avoid transcoding the svg to a png file.

   BTW there isn't much difference between this route and using a PNG
(for mid/high resolution the SVG will be smaller and in many
cases more flexible).

> Is there a Batik API call to achieve this?

   If you mean a single 'high level' java call to do this, No.
The code you have below is roughly the simplest version of
the code.

> All I could find is this relatively complex solution…

   So I've often considered adding such a call but given
than at least on the surface 90% of users of the transcoders
API's want to tweak this or that parameter of the transcoding
processes (at least width/height, often what part of canvas,
contents of document, run onload handlers etc).  It's always 
seemed like many users would end up needing something more. 
Even below you seem to have some form of scale you are 
manipulating (scaleX/Y), so such a simple call would not 
have helped you much...

   SVG is not like a PNG, there is no real inherent pixel size.

   BTW if you want to keep the transparent background then
I would suggest using TYPE_INT_ARGB instead of just RGB.

> String parser = XMLResourceDescriptor.getXMLParserClassName();
> SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser);
> 
> File file = new File(MyClass.class.getResource("test.svg").getFile());
> document = (SVGDocument) f.createDocument(file.toURL().toString());
> 
> // Build the tree and get the document dimensions
> UserAgentAdapter userAgentAdapter = new UserAgentAdapter();
> BridgeContext bridgeContext = new BridgeContext(userAgentAdapter);
> GVTBuilder builder = new GVTBuilder();
> GraphicsNode graphicsNode = builder.build(bridgeContext, document);
> 
> BufferedImage bufferedImage = new BufferedImage
>          ((int)(bounds.getWidth() * scaleX), 
>           (int)(bounds.getHeight() * scaleY), 
>           BufferedImage.TYPE_INT_RGB);
> Graphics2D g2d = (Graphics2D) bufferedImage.getGraphics();
> graphicsNode.paint(g2d);
> g2d.dispose();
> 
> return bufferedImage;
> 
> LEGAL NOTICE:
> Unless expressly stated otherwise, this message is confidential and may 
be 
> privileged. It is intended for the addressee(s) only. Access to this 
e-mail by
> anyone else is unauthorized. If you are not an addressee, any disclosure 
or 
> copying of the contents or any action taken (or not taken) in reliance 
on it 
> is unauthorized and may be unlawful. If you are not an addressee, please 

> inform the sender immediately.