Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swing & Batik: Create an ImageIcon from an SVG file?

Tags:

Simply put, I'm looking for a way to make an ImageIcon from an SVG file using the batik library. I don't want to have to raster the SVG to disk first, I just want to be able to pull an svg out of the jar file and have it land as a UI element.

I feel like this should be reasonably easy, but the batik javadocs aren't telling me what I need to know.

(Why batik? Well, we're already using it, so we don't have to run another library past legal.)

like image 965
Electrons_Ahoy Avatar asked Mar 22 '10 20:03

Electrons_Ahoy


2 Answers

It's really quite easy, just not very intuitive.

You need to extend ImageTranscoder. In the createImage method you allocate a BufferedImage, cache it as a member variable, and return it. The writeImage method is empty. And you'll need to add a getter to retrieve the BufferedImage.

It will look something like this:

    class MyTranscoder extends ImageTranscoder {         private BufferedImage image = null;         public BufferedImage createImage(int w, int h) {             image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);             return image;         }         public void writeImage(BufferedImage img, TranscoderOutput out) {         }         public BufferedImage getImage() {             return image;         }     } 

Now, to create an image you create an instance of your transcoder and pass it the desired width and height by setting TranscodingHints. Finally you transcode from a TranscoderInput to a null target. Then call the getter on your transcoder to obtain the image.

The call looks something like this:

    MyTranscoder transcoder = new MyTranscoder();     TranscodingHints hints = new TranscodingHints();     hints.put(ImageTranscoder.KEY_WIDTH, width);     hints.put(ImageTranscoder.KEY_HEIGHT, height);     transcoder.setTranscodingHints(hints);     transcoder.transcode(new TranscoderInput(url), null);     BufferedImage image = transcoder.getImage(); 

Simple, right? (Yeah, right. Only took me 2 weeks to figure that out. Sigh.)

like image 64
Devon_C_Miller Avatar answered Nov 07 '22 18:11

Devon_C_Miller


I have just followed Devon's approach with Batik-1.7

However, in order to make it work I had to make the following additions to the hints object:

MyTranscoder transcoder =new MyTranscoder()  DOMImplementation impl = SVGDOMImplementation.getDOMImplementation(); TranscodingHints hints = new TranscodingHints(); hints.put(ImageTranscoder.KEY_WIDTH, width); // e.g. width=new Float(300) hints.put(ImageTranscoder.KEY_HEIGHT,height);// e.g. height=new Float(75) hints.put(ImageTranscoder.KEY_DOM_IMPLEMENTATION, impl.getDOMImplementation()); hints.put(ImageTranscoder.KEY_DOCUMENT_ELEMENT_NAMESPACE_URI,SVGConstants.SVG_NAMESPACE_URI); hints.put(ImageTranscoder.KEY_DOCUMENT_ELEMENT_NAMESPACE_URI,SVGConstants.SVG_NAMESPACE_URI); hints.put(ImageTranscoder.KEY_DOCUMENT_ELEMENT, SVGConstants.SVG_SVG_TAG); hints.put(ImageTranscoder.KEY_XML_PARSER_VALIDATING, false);  transcoder.setTranscodingHints(hints); TranscoderInput ti=new TranscoderInput(uri) transcoder.transcode(ti, null); BufferedImage image = transcoder.getImage(); 

Seems like something has been updated in batik's XMLAbstractTranscoder( http://svn.apache.org/repos/asf/xmlgraphics/batik/tags/batik-1_7/sources/org/apache/batik/transcoder/XMLAbstractTranscoder.java) with version 1.7.

like image 36
John Doppelmann Avatar answered Nov 07 '22 18:11

John Doppelmann