4

I'd like to display a svg image in javafx 2.0, but I don't find such a thing in the API. I guess it's because it's still in beta.

Until the final release, how can I load a svg ? Is there already a library which can handle that, or do I need to parse myself the file and then create the corresponding shapes ?

Thanks

leppie
  • 109,129
  • 16
  • 185
  • 292
Mr_Qqn
  • 1,508
  • 2
  • 13
  • 17

5 Answers5

8

Based on the answer of this question I found a working solution.

1. Include references to the Batik SVG Toolkit jars

2. Implement your own Transcoder
(based on this answer by Devon_C_Miller)

class MyTranscoder extends ImageTranscoder {

    private BufferedImage image = null;

    @Override
    public BufferedImage createImage(int w, int h) {
        image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
        return image;
    }

    @Override
    public void writeImage(BufferedImage img, TranscoderOutput out) {
    }

    public BufferedImage getImage() {
        return image;
    }

}

3. Get a BufferedImage from your svg
(based on hint in this answer by John Doppelmann)

String uri = "path_to_svg/some.svg";

MyTranscoder transcoder = new MyTranscoder();
TranscodingHints hints = new TranscodingHints();
hints.put(ImageTranscoder.KEY_WIDTH, 20f); //your image width
hints.put(ImageTranscoder.KEY_HEIGHT, 20f); //your image height
hints.put(ImageTranscoder.KEY_DOM_IMPLEMENTATION,    SVGDOMImplementation.getDOMImplementation());
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 input = new TranscoderInput(url.toExternalForm());
transcoder.transcode(input, null);
BufferedImage bufferedImage = transcoder.getImage();

4. Create an InputStream from BufferedImage

ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

JPEGImageEncoder imageEncoder = JPEGCodec.createJPEGEncoder(outputStream);
imageEncoder.encode(bufferedImage);

byte[] bytes = outputStream.toByteArray();
InputStream inputStream = new ByteArrayInputStream(bytes);

5. Add the image to your ImageView

//javafx.scene.image.Image
Image image = new Image(inputStream);
//javafx.scene.image.ImageView
ImageView imageView = new ImageView();
imageView.setImage(image);
this.getChildren().add(imageView);

Hope this will help!

Community
  • 1
  • 1
pmoule
  • 4,062
  • 2
  • 30
  • 38
  • Thanks ! But don't javafx handle raw image data ? – Mr_Qqn Jul 30 '11 at 09:23
  • @Mr_Qqn: Currently I don't know about any support concerning handling raw image data. Personally, I would prefer an ability of the API to convert SVG files to Java code as described [here](http://silveiraneto.net/2008/11/21/inkscape-and-javafx-working-together/). – pmoule Jul 30 '11 at 11:15
  • But unlike fx scripts java classes are compiled, so I don't think that would be a good thing. – Mr_Qqn Aug 01 '11 at 10:53
  • 4. After you get buffered image, you could do byte[] bytes = bufferedImage.toByteArray(); ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes); BufferedImage image = ImageIO.read(inputStream); Image im = SwingFXUtils.toFXImage(image, null); – Ondrej Kvasnovsky Feb 22 '16 at 06:40
3

I used @pmoule's answer above, but had better luck replacing his steps 3-5 with this:

MyTranscoder imageTranscoder = new MyTranscoder();

imageTranscoder.addTranscodingHint(PNGTranscoder.KEY_WIDTH, (float) width);
imageTranscoder.addTranscodingHint(PNGTranscoder.KEY_HEIGHT, (float) height);

TranscoderInput input = new TranscoderInput(new FileReader(file));
imageTranscoder.transcode(input, null);

BufferedImage bimage =  imageTranscoder.getImage();
WritableImage wimage = SwingFXUtils.toFXImage(bimage, null);
ImageView imageView = new ImageView(wimage);
<panel-vbox-whatever>.getChildren().clear();
<panel-vbox-whatever>.getChildren().add(imageView);

Simpler, and it just worked better for me.

8forty
  • 524
  • 4
  • 13
1

you do not need batik, you can try WebView like this:

WebView view = new WebView();
view.setMinSize(500, 400);
view.setPrefSize(500, 400);
final WebEngine eng = view.getEngine();
eng.load("http://127.0.0.1/demo1.svg");
0

Convert the SVG to FXML and then it becomes trivial. The conversion can be done with XSLT. You can get the stylesheet from here:

http://jayskills.com/blog/2012/06/03/svg-to-fxml-using-netbeans/

Then after conversion to FXML you can load it as a Node with the built-in FXMLLoader:

FXMLLoader.setDefaultClassLoader(this.getClass().getClassLoader());
URL location = KayakMain.class.getResource("path/to/my/resource.fxml");
Parent root = FXMLLoader.load(location);
swpalmer
  • 2,118
  • 17
  • 23