How to get a BufferedImage from a SVG?












18















I am using Batik to handle SVG images. Is there any way to get a java.awt.image.BufferedImage from a SVG-file?



I know there are transcoders, with which I could transcode the SVG into, for example, a PNG and then load that PNG with ImageIO.read()· But I don't want to have the temporary file.










share|improve this question





























    18















    I am using Batik to handle SVG images. Is there any way to get a java.awt.image.BufferedImage from a SVG-file?



    I know there are transcoders, with which I could transcode the SVG into, for example, a PNG and then load that PNG with ImageIO.read()· But I don't want to have the temporary file.










    share|improve this question



























      18












      18








      18


      7






      I am using Batik to handle SVG images. Is there any way to get a java.awt.image.BufferedImage from a SVG-file?



      I know there are transcoders, with which I could transcode the SVG into, for example, a PNG and then load that PNG with ImageIO.read()· But I don't want to have the temporary file.










      share|improve this question
















      I am using Batik to handle SVG images. Is there any way to get a java.awt.image.BufferedImage from a SVG-file?



      I know there are transcoders, with which I could transcode the SVG into, for example, a PNG and then load that PNG with ImageIO.read()· But I don't want to have the temporary file.







      java svg batik






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Mar 21 at 10:57









      marcolopes

      4,660124261




      4,660124261










      asked Jul 11 '12 at 15:06









      mr_georgmr_georg

      1,97642740




      1,97642740
























          3 Answers
          3






          active

          oldest

          votes


















          19














          Using Batik, something like this:



          public static BufferedImage rasterize(File svgFile) throws IOException {

          final BufferedImage imagePointer = new BufferedImage[1];

          // Rendering hints can't be set programatically, so
          // we override defaults with a temporary stylesheet.
          // These defaults emphasize quality and precision, and
          // are more similar to the defaults of other SVG viewers.
          // SVG documents can still override these defaults.
          String css = "svg {" +
          "shape-rendering: geometricPrecision;" +
          "text-rendering: geometricPrecision;" +
          "color-rendering: optimizeQuality;" +
          "image-rendering: optimizeQuality;" +
          "}";
          File cssFile = File.createTempFile("batik-default-override-", ".css");
          FileUtils.writeStringToFile(cssFile, css);

          TranscodingHints transcoderHints = new TranscodingHints();
          transcoderHints.put(ImageTranscoder.KEY_XML_PARSER_VALIDATING, Boolean.FALSE);
          transcoderHints.put(ImageTranscoder.KEY_DOM_IMPLEMENTATION,
          SVGDOMImplementation.getDOMImplementation());
          transcoderHints.put(ImageTranscoder.KEY_DOCUMENT_ELEMENT_NAMESPACE_URI,
          SVGConstants.SVG_NAMESPACE_URI);
          transcoderHints.put(ImageTranscoder.KEY_DOCUMENT_ELEMENT, "svg");
          transcoderHints.put(ImageTranscoder.KEY_USER_STYLESHEET_URI, cssFile.toURI().toString());

          try {

          TranscoderInput input = new TranscoderInput(new FileInputStream(svgFile));

          ImageTranscoder t = new ImageTranscoder() {

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

          @Override
          public void writeImage(BufferedImage image, TranscoderOutput out)
          throws TranscoderException {
          imagePointer[0] = image;
          }
          };
          t.setTranscodingHints(transcoderHints);
          t.transcode(input, null);
          }
          catch (TranscoderException ex) {
          // Requires Java 6
          ex.printStackTrace();
          throw new IOException("Couldn't convert " + svgFile);
          }
          finally {
          cssFile.delete();
          }

          return imagePointer[0];
          }





          share|improve this answer


























          • is there an advantage to creating an array of imagePointer vs just assigning imagePointer to a local variable like this bbgen.net/blog/2011/06/java-svg-to-bufferedimage?

            – jon_wu
            Jun 18 '14 at 3:47











          • Actually no. It's just an workaround to avoid compilation errors in the writeImage method.

            – elias
            Jun 18 '14 at 13:55













          • Ah cool. Thanks for verifying!

            – jon_wu
            Jun 20 '14 at 1:14











          • I figured out how to set size by using e.g transcoderHints.put(ImageTranscoder.KEY_WIDTH..., but how would I scale the output image by a factor?

            – vincent
            Aug 30 '17 at 2:20











          • @vincent "by a factor" you mean zoom X%?

            – elias
            Aug 30 '17 at 14:16



















          12














          A very easy way is to use the TwelveMonkeys lib which adds additional image type support to java's ImageIO



          So for example you just add these to your maven (or copy the needed jars):



              <dependency>
          <groupId>com.twelvemonkeys.imageio</groupId>
          <artifactId>imageio-batik</artifactId> <!-- svg -->
          <version>3.2.1</version>
          </dependency>
          <dependency>
          <groupId>batik</groupId>
          <artifactId>batik-transcoder</artifactId>
          <version>1.6-1</version>
          </dependency>


          And then you just read it with



          BufferedImage image = ImageIO.read(svg-file);


          To check if the svg reader is registered correctly you could print out the image readers:



          Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("SVG");
          while (readers.hasNext()) {
          System.out.println("reader: " + readers.next());
          }


          The lib also supports additional params, see readme on github.






          share|improve this answer
























          • This is weird lib. It haven't online documentation. It haven't examples. It have problem with dependency (see your post with third party). And it's have problem with icon resize-load. I was led to a small amount of code and regretted it.

            – JayDi
            Nov 24 '17 at 12:32



















          2














          This is what I use. It's an extension of BufferedImage with its own static factory that can be used wherever a BufferedImage is used. I wrote it so that any call to getScaledInstance(w, h, hint) will render from the SVG, not the rasterized image. A side-effect of this is that the scaling hint parameter has no meaning; you can just pass 0 or DEFAULT to that. It renders lazily - only when graphics data is requested - so the load / scale cycle shouldn't give you too much overhead.



          Edit: I added support using the above CSS config for scaling quality hints.
          Edit 2: Lazy rendering wasn't working consistently; I put the render() call into the constructor.



          It has the following dependencies:




          • org.apache.xmlgraphics:batik-anim

          • org.apache.xmlgraphics:batik-bridge

          • org.apache.xmlgraphics:batik-gvt

          • org.apache.xmlgraphics:batik-transcoder

          • org.apache.xmlgraphics:batik-util

          • xml-apis:xml-apis-ext

          • commons-logging:commons-logging


          When I made this, I used batik 1.8; YMMV.



          import java.awt.AlphaComposite;
          import java.awt.Composite;
          import java.awt.Graphics;
          import java.awt.Graphics2D;
          import java.awt.Image;
          import java.awt.image.BufferedImage;
          import java.awt.image.Raster;
          import java.awt.image.WritableRaster;
          import java.io.File;
          import java.io.FileWriter;
          import java.io.IOException;
          import java.io.InputStream;
          import java.net.URL;
          import java.util.HashMap;
          import java.util.Map;

          import org.apache.batik.anim.dom.SAXSVGDocumentFactory;
          import org.apache.batik.bridge.BridgeContext;
          import org.apache.batik.bridge.DocumentLoader;
          import org.apache.batik.bridge.GVTBuilder;
          import org.apache.batik.bridge.UserAgent;
          import org.apache.batik.bridge.UserAgentAdapter;
          import org.apache.batik.gvt.GraphicsNode;
          import org.apache.batik.transcoder.TranscoderException;
          import org.apache.batik.transcoder.TranscoderInput;
          import org.apache.batik.transcoder.TranscoderOutput;
          import org.apache.batik.transcoder.TranscodingHints;
          import org.apache.batik.transcoder.image.ImageTranscoder;
          import org.apache.batik.util.SVGConstants;
          import org.apache.batik.util.XMLResourceDescriptor;
          import org.apache.commons.logging.Log;
          import org.apache.commons.logging.LogFactory;
          import org.w3c.dom.svg.SVGDocument;

          public class SVGImage extends BufferedImage {
          private static class BufferedImageTranscoder extends ImageTranscoder {
          private BufferedImage image = null;
          @Override
          public BufferedImage createImage(int arg0, int arg1) {

          return image;
          }
          private void setImage(BufferedImage image) {
          this.image = image;
          }
          @Override
          public void writeImage(BufferedImage arg0, TranscoderOutput arg1) throws TranscoderException {
          }
          }

          final static GVTBuilder builder = new GVTBuilder();
          final static SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(XMLResourceDescriptor.getXMLParserClassName());
          final static UserAgent userAgent = new UserAgentAdapter();
          final static DocumentLoader loader = new DocumentLoader(userAgent);
          final static BridgeContext bridgeContext = new BridgeContext(userAgent, loader);
          static {
          bridgeContext.setDynamicState(BridgeContext.STATIC);
          }
          final static private Log log = LogFactory.getLog(SVGImage.class);
          private static final Map<Integer, String> scaleQuality = new HashMap<Integer, String>();
          static {
          String css = "svg {" +
          "shape-rendering: %s;" +
          "text-rendering: %s;" +
          "color-rendering: %s;" +
          "image-rendering: %s;" +
          "}";
          String precise = "geometricPrecision";
          String quality = "optimizeQuality";
          String speed = "optimizeSpeed";
          String crisp = "crispEdges";
          String legible = "optimizeLegibility";
          String auto = "auto";

          scaleQuality.put(SCALE_DEFAULT, String.format(css, auto, auto, auto, auto));
          scaleQuality.put(SCALE_SMOOTH, String.format(css, precise, precise, quality, quality));
          scaleQuality.put(SCALE_REPLICATE, String.format(css, speed, speed, speed, speed));
          scaleQuality.put(SCALE_AREA_AVERAGING, String.format(css, crisp, legible, auto, auto));
          scaleQuality.put(SCALE_FAST, String.format(css, speed, speed, speed, speed));
          }
          final static BufferedImageTranscoder transcoder = new BufferedImageTranscoder();

          public static SVGImage fromSvg(URL resource) throws IOException {
          InputStream rs = null;
          try {
          rs = resource.openStream();
          SVGDocument svg = factory.createSVGDocument(resource.toString(), rs);
          return fromSvgDocument(resource, svg);
          } finally {
          if (rs != null) {
          try { rs.close(); } catch (IOException ioe) {}
          }
          }
          }
          public static SVGImage fromSvgDocument(URL resource, SVGDocument doc) {
          GraphicsNode graphicsNode = builder.build(bridgeContext, doc);
          Double width = graphicsNode.getBounds().getWidth();
          Double height = graphicsNode.getBounds().getHeight();
          return new SVGImage(resource, doc, width.intValue(), height.intValue(), SCALE_DEFAULT);
          }
          boolean hasRendered = false;
          private int scalingHint = SCALE_DEFAULT;
          final SVGDocument svg;
          final URL svgUrl;
          private SVGImage(URL resource, SVGDocument doc, int width, int height, int hints) {
          super(width, height, TYPE_INT_ARGB);
          scalingHint = hints;
          svgUrl = resource;
          svg = doc;
          render();
          }
          @Override
          public void coerceData(boolean isAlphaPremultiplied) {
          if (!hasRendered) { render(); }
          super.coerceData(isAlphaPremultiplied);
          }
          @Override
          public WritableRaster copyData(WritableRaster outRaster) {
          if (!hasRendered) { render(); }
          return super.copyData(outRaster);
          }
          private File createCSS(String css) {
          FileWriter cssWriter = null;
          File cssFile = null;
          try {
          cssFile = File.createTempFile("batik-default-override-", ".css");
          cssFile.deleteOnExit();
          cssWriter = new FileWriter(cssFile);
          cssWriter.write(css);
          } catch(IOException ioe) {
          log.warn("Couldn't write stylesheet; SVG rendered with Batik defaults");
          } finally {

          if (cssWriter != null) {
          try {
          cssWriter.flush();
          cssWriter.close();
          } catch (IOException ioe) {}
          }
          }
          return cssFile;
          }
          @Override
          public WritableRaster getAlphaRaster() {
          if (!hasRendered) { render(); }
          return super.getAlphaRaster();
          }
          @Override
          public Raster getData() {
          if (!hasRendered) { render(); }
          return super.getData();
          }

          @Override
          public Graphics getGraphics() {
          if (!hasRendered) { render(); }
          return super.getGraphics();
          }
          public Image getScaledInstance(int width, int height, int hints) {
          SVGImage newImage = new SVGImage(svgUrl, svg, width, height, hints);
          return newImage;
          }
          private void render() {
          TranscodingHints hints = new TranscodingHints();
          hints.put(ImageTranscoder.KEY_WIDTH, new Float(getWidth()));
          hints.put(ImageTranscoder.KEY_HEIGHT, new Float(getHeight()));
          hints.put(ImageTranscoder.KEY_XML_PARSER_VALIDATING, Boolean.FALSE);
          hints.put(ImageTranscoder.KEY_DOM_IMPLEMENTATION, svg.getImplementation());
          hints.put(ImageTranscoder.KEY_DOCUMENT_ELEMENT_NAMESPACE_URI, SVGConstants.SVG_NAMESPACE_URI);
          hints.put(ImageTranscoder.KEY_DOCUMENT_ELEMENT, "svg");
          String css = scaleQuality.get(scalingHint);
          File cssFile = null;
          if (css != null) {
          cssFile = createCSS(css);
          if (cssFile != null) {
          hints.put(ImageTranscoder.KEY_USER_STYLESHEET_URI, cssFile.toURI().toString());
          }
          }
          transcoder.setTranscodingHints(hints);
          transcoder.setImage(this);
          // This may be a re-render, if the scaling quality hint has changed.
          // As such, we force the image into overwrite mode, and kick it back when we're done / fail
          Graphics2D gfx = (Graphics2D) super.getGraphics();
          Composite savedComposite = gfx.getComposite();
          gfx.setComposite(AlphaComposite.Clear);
          try {
          transcoder.transcode(new TranscoderInput(svg), null);
          hasRendered = true;
          } catch (TranscoderException te) {
          log.warn("Could not transcode " + svgUrl.getPath() + " to raster image; you're going to get a blank BufferedImage of the correct size.");
          } finally {
          gfx.setComposite(savedComposite);
          if (cssFile != null) {
          cssFile.delete();
          }
          }
          }
          public void setScalingHint(int hint) {
          this.scalingHint = hint;
          // Forces a re-render
          this.hasRendered = false;
          }
          }





          share|improve this answer


























          • Incidentally, I think I'll be stealing the CSS transcoder hint above to emulate the scaling hints from BufferedImage.

            – Fordi
            Jun 14 '15 at 5:43












          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f11435671%2fhow-to-get-a-bufferedimage-from-a-svg%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          3 Answers
          3






          active

          oldest

          votes








          3 Answers
          3






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          19














          Using Batik, something like this:



          public static BufferedImage rasterize(File svgFile) throws IOException {

          final BufferedImage imagePointer = new BufferedImage[1];

          // Rendering hints can't be set programatically, so
          // we override defaults with a temporary stylesheet.
          // These defaults emphasize quality and precision, and
          // are more similar to the defaults of other SVG viewers.
          // SVG documents can still override these defaults.
          String css = "svg {" +
          "shape-rendering: geometricPrecision;" +
          "text-rendering: geometricPrecision;" +
          "color-rendering: optimizeQuality;" +
          "image-rendering: optimizeQuality;" +
          "}";
          File cssFile = File.createTempFile("batik-default-override-", ".css");
          FileUtils.writeStringToFile(cssFile, css);

          TranscodingHints transcoderHints = new TranscodingHints();
          transcoderHints.put(ImageTranscoder.KEY_XML_PARSER_VALIDATING, Boolean.FALSE);
          transcoderHints.put(ImageTranscoder.KEY_DOM_IMPLEMENTATION,
          SVGDOMImplementation.getDOMImplementation());
          transcoderHints.put(ImageTranscoder.KEY_DOCUMENT_ELEMENT_NAMESPACE_URI,
          SVGConstants.SVG_NAMESPACE_URI);
          transcoderHints.put(ImageTranscoder.KEY_DOCUMENT_ELEMENT, "svg");
          transcoderHints.put(ImageTranscoder.KEY_USER_STYLESHEET_URI, cssFile.toURI().toString());

          try {

          TranscoderInput input = new TranscoderInput(new FileInputStream(svgFile));

          ImageTranscoder t = new ImageTranscoder() {

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

          @Override
          public void writeImage(BufferedImage image, TranscoderOutput out)
          throws TranscoderException {
          imagePointer[0] = image;
          }
          };
          t.setTranscodingHints(transcoderHints);
          t.transcode(input, null);
          }
          catch (TranscoderException ex) {
          // Requires Java 6
          ex.printStackTrace();
          throw new IOException("Couldn't convert " + svgFile);
          }
          finally {
          cssFile.delete();
          }

          return imagePointer[0];
          }





          share|improve this answer


























          • is there an advantage to creating an array of imagePointer vs just assigning imagePointer to a local variable like this bbgen.net/blog/2011/06/java-svg-to-bufferedimage?

            – jon_wu
            Jun 18 '14 at 3:47











          • Actually no. It's just an workaround to avoid compilation errors in the writeImage method.

            – elias
            Jun 18 '14 at 13:55













          • Ah cool. Thanks for verifying!

            – jon_wu
            Jun 20 '14 at 1:14











          • I figured out how to set size by using e.g transcoderHints.put(ImageTranscoder.KEY_WIDTH..., but how would I scale the output image by a factor?

            – vincent
            Aug 30 '17 at 2:20











          • @vincent "by a factor" you mean zoom X%?

            – elias
            Aug 30 '17 at 14:16
















          19














          Using Batik, something like this:



          public static BufferedImage rasterize(File svgFile) throws IOException {

          final BufferedImage imagePointer = new BufferedImage[1];

          // Rendering hints can't be set programatically, so
          // we override defaults with a temporary stylesheet.
          // These defaults emphasize quality and precision, and
          // are more similar to the defaults of other SVG viewers.
          // SVG documents can still override these defaults.
          String css = "svg {" +
          "shape-rendering: geometricPrecision;" +
          "text-rendering: geometricPrecision;" +
          "color-rendering: optimizeQuality;" +
          "image-rendering: optimizeQuality;" +
          "}";
          File cssFile = File.createTempFile("batik-default-override-", ".css");
          FileUtils.writeStringToFile(cssFile, css);

          TranscodingHints transcoderHints = new TranscodingHints();
          transcoderHints.put(ImageTranscoder.KEY_XML_PARSER_VALIDATING, Boolean.FALSE);
          transcoderHints.put(ImageTranscoder.KEY_DOM_IMPLEMENTATION,
          SVGDOMImplementation.getDOMImplementation());
          transcoderHints.put(ImageTranscoder.KEY_DOCUMENT_ELEMENT_NAMESPACE_URI,
          SVGConstants.SVG_NAMESPACE_URI);
          transcoderHints.put(ImageTranscoder.KEY_DOCUMENT_ELEMENT, "svg");
          transcoderHints.put(ImageTranscoder.KEY_USER_STYLESHEET_URI, cssFile.toURI().toString());

          try {

          TranscoderInput input = new TranscoderInput(new FileInputStream(svgFile));

          ImageTranscoder t = new ImageTranscoder() {

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

          @Override
          public void writeImage(BufferedImage image, TranscoderOutput out)
          throws TranscoderException {
          imagePointer[0] = image;
          }
          };
          t.setTranscodingHints(transcoderHints);
          t.transcode(input, null);
          }
          catch (TranscoderException ex) {
          // Requires Java 6
          ex.printStackTrace();
          throw new IOException("Couldn't convert " + svgFile);
          }
          finally {
          cssFile.delete();
          }

          return imagePointer[0];
          }





          share|improve this answer


























          • is there an advantage to creating an array of imagePointer vs just assigning imagePointer to a local variable like this bbgen.net/blog/2011/06/java-svg-to-bufferedimage?

            – jon_wu
            Jun 18 '14 at 3:47











          • Actually no. It's just an workaround to avoid compilation errors in the writeImage method.

            – elias
            Jun 18 '14 at 13:55













          • Ah cool. Thanks for verifying!

            – jon_wu
            Jun 20 '14 at 1:14











          • I figured out how to set size by using e.g transcoderHints.put(ImageTranscoder.KEY_WIDTH..., but how would I scale the output image by a factor?

            – vincent
            Aug 30 '17 at 2:20











          • @vincent "by a factor" you mean zoom X%?

            – elias
            Aug 30 '17 at 14:16














          19












          19








          19







          Using Batik, something like this:



          public static BufferedImage rasterize(File svgFile) throws IOException {

          final BufferedImage imagePointer = new BufferedImage[1];

          // Rendering hints can't be set programatically, so
          // we override defaults with a temporary stylesheet.
          // These defaults emphasize quality and precision, and
          // are more similar to the defaults of other SVG viewers.
          // SVG documents can still override these defaults.
          String css = "svg {" +
          "shape-rendering: geometricPrecision;" +
          "text-rendering: geometricPrecision;" +
          "color-rendering: optimizeQuality;" +
          "image-rendering: optimizeQuality;" +
          "}";
          File cssFile = File.createTempFile("batik-default-override-", ".css");
          FileUtils.writeStringToFile(cssFile, css);

          TranscodingHints transcoderHints = new TranscodingHints();
          transcoderHints.put(ImageTranscoder.KEY_XML_PARSER_VALIDATING, Boolean.FALSE);
          transcoderHints.put(ImageTranscoder.KEY_DOM_IMPLEMENTATION,
          SVGDOMImplementation.getDOMImplementation());
          transcoderHints.put(ImageTranscoder.KEY_DOCUMENT_ELEMENT_NAMESPACE_URI,
          SVGConstants.SVG_NAMESPACE_URI);
          transcoderHints.put(ImageTranscoder.KEY_DOCUMENT_ELEMENT, "svg");
          transcoderHints.put(ImageTranscoder.KEY_USER_STYLESHEET_URI, cssFile.toURI().toString());

          try {

          TranscoderInput input = new TranscoderInput(new FileInputStream(svgFile));

          ImageTranscoder t = new ImageTranscoder() {

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

          @Override
          public void writeImage(BufferedImage image, TranscoderOutput out)
          throws TranscoderException {
          imagePointer[0] = image;
          }
          };
          t.setTranscodingHints(transcoderHints);
          t.transcode(input, null);
          }
          catch (TranscoderException ex) {
          // Requires Java 6
          ex.printStackTrace();
          throw new IOException("Couldn't convert " + svgFile);
          }
          finally {
          cssFile.delete();
          }

          return imagePointer[0];
          }





          share|improve this answer















          Using Batik, something like this:



          public static BufferedImage rasterize(File svgFile) throws IOException {

          final BufferedImage imagePointer = new BufferedImage[1];

          // Rendering hints can't be set programatically, so
          // we override defaults with a temporary stylesheet.
          // These defaults emphasize quality and precision, and
          // are more similar to the defaults of other SVG viewers.
          // SVG documents can still override these defaults.
          String css = "svg {" +
          "shape-rendering: geometricPrecision;" +
          "text-rendering: geometricPrecision;" +
          "color-rendering: optimizeQuality;" +
          "image-rendering: optimizeQuality;" +
          "}";
          File cssFile = File.createTempFile("batik-default-override-", ".css");
          FileUtils.writeStringToFile(cssFile, css);

          TranscodingHints transcoderHints = new TranscodingHints();
          transcoderHints.put(ImageTranscoder.KEY_XML_PARSER_VALIDATING, Boolean.FALSE);
          transcoderHints.put(ImageTranscoder.KEY_DOM_IMPLEMENTATION,
          SVGDOMImplementation.getDOMImplementation());
          transcoderHints.put(ImageTranscoder.KEY_DOCUMENT_ELEMENT_NAMESPACE_URI,
          SVGConstants.SVG_NAMESPACE_URI);
          transcoderHints.put(ImageTranscoder.KEY_DOCUMENT_ELEMENT, "svg");
          transcoderHints.put(ImageTranscoder.KEY_USER_STYLESHEET_URI, cssFile.toURI().toString());

          try {

          TranscoderInput input = new TranscoderInput(new FileInputStream(svgFile));

          ImageTranscoder t = new ImageTranscoder() {

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

          @Override
          public void writeImage(BufferedImage image, TranscoderOutput out)
          throws TranscoderException {
          imagePointer[0] = image;
          }
          };
          t.setTranscodingHints(transcoderHints);
          t.transcode(input, null);
          }
          catch (TranscoderException ex) {
          // Requires Java 6
          ex.printStackTrace();
          throw new IOException("Couldn't convert " + svgFile);
          }
          finally {
          cssFile.delete();
          }

          return imagePointer[0];
          }






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 19 '12 at 12:24

























          answered Jul 11 '12 at 15:57









          eliaselias

          9,61533057




          9,61533057













          • is there an advantage to creating an array of imagePointer vs just assigning imagePointer to a local variable like this bbgen.net/blog/2011/06/java-svg-to-bufferedimage?

            – jon_wu
            Jun 18 '14 at 3:47











          • Actually no. It's just an workaround to avoid compilation errors in the writeImage method.

            – elias
            Jun 18 '14 at 13:55













          • Ah cool. Thanks for verifying!

            – jon_wu
            Jun 20 '14 at 1:14











          • I figured out how to set size by using e.g transcoderHints.put(ImageTranscoder.KEY_WIDTH..., but how would I scale the output image by a factor?

            – vincent
            Aug 30 '17 at 2:20











          • @vincent "by a factor" you mean zoom X%?

            – elias
            Aug 30 '17 at 14:16



















          • is there an advantage to creating an array of imagePointer vs just assigning imagePointer to a local variable like this bbgen.net/blog/2011/06/java-svg-to-bufferedimage?

            – jon_wu
            Jun 18 '14 at 3:47











          • Actually no. It's just an workaround to avoid compilation errors in the writeImage method.

            – elias
            Jun 18 '14 at 13:55













          • Ah cool. Thanks for verifying!

            – jon_wu
            Jun 20 '14 at 1:14











          • I figured out how to set size by using e.g transcoderHints.put(ImageTranscoder.KEY_WIDTH..., but how would I scale the output image by a factor?

            – vincent
            Aug 30 '17 at 2:20











          • @vincent "by a factor" you mean zoom X%?

            – elias
            Aug 30 '17 at 14:16

















          is there an advantage to creating an array of imagePointer vs just assigning imagePointer to a local variable like this bbgen.net/blog/2011/06/java-svg-to-bufferedimage?

          – jon_wu
          Jun 18 '14 at 3:47





          is there an advantage to creating an array of imagePointer vs just assigning imagePointer to a local variable like this bbgen.net/blog/2011/06/java-svg-to-bufferedimage?

          – jon_wu
          Jun 18 '14 at 3:47













          Actually no. It's just an workaround to avoid compilation errors in the writeImage method.

          – elias
          Jun 18 '14 at 13:55







          Actually no. It's just an workaround to avoid compilation errors in the writeImage method.

          – elias
          Jun 18 '14 at 13:55















          Ah cool. Thanks for verifying!

          – jon_wu
          Jun 20 '14 at 1:14





          Ah cool. Thanks for verifying!

          – jon_wu
          Jun 20 '14 at 1:14













          I figured out how to set size by using e.g transcoderHints.put(ImageTranscoder.KEY_WIDTH..., but how would I scale the output image by a factor?

          – vincent
          Aug 30 '17 at 2:20





          I figured out how to set size by using e.g transcoderHints.put(ImageTranscoder.KEY_WIDTH..., but how would I scale the output image by a factor?

          – vincent
          Aug 30 '17 at 2:20













          @vincent "by a factor" you mean zoom X%?

          – elias
          Aug 30 '17 at 14:16





          @vincent "by a factor" you mean zoom X%?

          – elias
          Aug 30 '17 at 14:16













          12














          A very easy way is to use the TwelveMonkeys lib which adds additional image type support to java's ImageIO



          So for example you just add these to your maven (or copy the needed jars):



              <dependency>
          <groupId>com.twelvemonkeys.imageio</groupId>
          <artifactId>imageio-batik</artifactId> <!-- svg -->
          <version>3.2.1</version>
          </dependency>
          <dependency>
          <groupId>batik</groupId>
          <artifactId>batik-transcoder</artifactId>
          <version>1.6-1</version>
          </dependency>


          And then you just read it with



          BufferedImage image = ImageIO.read(svg-file);


          To check if the svg reader is registered correctly you could print out the image readers:



          Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("SVG");
          while (readers.hasNext()) {
          System.out.println("reader: " + readers.next());
          }


          The lib also supports additional params, see readme on github.






          share|improve this answer
























          • This is weird lib. It haven't online documentation. It haven't examples. It have problem with dependency (see your post with third party). And it's have problem with icon resize-load. I was led to a small amount of code and regretted it.

            – JayDi
            Nov 24 '17 at 12:32
















          12














          A very easy way is to use the TwelveMonkeys lib which adds additional image type support to java's ImageIO



          So for example you just add these to your maven (or copy the needed jars):



              <dependency>
          <groupId>com.twelvemonkeys.imageio</groupId>
          <artifactId>imageio-batik</artifactId> <!-- svg -->
          <version>3.2.1</version>
          </dependency>
          <dependency>
          <groupId>batik</groupId>
          <artifactId>batik-transcoder</artifactId>
          <version>1.6-1</version>
          </dependency>


          And then you just read it with



          BufferedImage image = ImageIO.read(svg-file);


          To check if the svg reader is registered correctly you could print out the image readers:



          Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("SVG");
          while (readers.hasNext()) {
          System.out.println("reader: " + readers.next());
          }


          The lib also supports additional params, see readme on github.






          share|improve this answer
























          • This is weird lib. It haven't online documentation. It haven't examples. It have problem with dependency (see your post with third party). And it's have problem with icon resize-load. I was led to a small amount of code and regretted it.

            – JayDi
            Nov 24 '17 at 12:32














          12












          12








          12







          A very easy way is to use the TwelveMonkeys lib which adds additional image type support to java's ImageIO



          So for example you just add these to your maven (or copy the needed jars):



              <dependency>
          <groupId>com.twelvemonkeys.imageio</groupId>
          <artifactId>imageio-batik</artifactId> <!-- svg -->
          <version>3.2.1</version>
          </dependency>
          <dependency>
          <groupId>batik</groupId>
          <artifactId>batik-transcoder</artifactId>
          <version>1.6-1</version>
          </dependency>


          And then you just read it with



          BufferedImage image = ImageIO.read(svg-file);


          To check if the svg reader is registered correctly you could print out the image readers:



          Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("SVG");
          while (readers.hasNext()) {
          System.out.println("reader: " + readers.next());
          }


          The lib also supports additional params, see readme on github.






          share|improve this answer













          A very easy way is to use the TwelveMonkeys lib which adds additional image type support to java's ImageIO



          So for example you just add these to your maven (or copy the needed jars):



              <dependency>
          <groupId>com.twelvemonkeys.imageio</groupId>
          <artifactId>imageio-batik</artifactId> <!-- svg -->
          <version>3.2.1</version>
          </dependency>
          <dependency>
          <groupId>batik</groupId>
          <artifactId>batik-transcoder</artifactId>
          <version>1.6-1</version>
          </dependency>


          And then you just read it with



          BufferedImage image = ImageIO.read(svg-file);


          To check if the svg reader is registered correctly you could print out the image readers:



          Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("SVG");
          while (readers.hasNext()) {
          System.out.println("reader: " + readers.next());
          }


          The lib also supports additional params, see readme on github.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Mar 5 '16 at 10:16









          patrickfpatrickf

          22.5k67297




          22.5k67297













          • This is weird lib. It haven't online documentation. It haven't examples. It have problem with dependency (see your post with third party). And it's have problem with icon resize-load. I was led to a small amount of code and regretted it.

            – JayDi
            Nov 24 '17 at 12:32



















          • This is weird lib. It haven't online documentation. It haven't examples. It have problem with dependency (see your post with third party). And it's have problem with icon resize-load. I was led to a small amount of code and regretted it.

            – JayDi
            Nov 24 '17 at 12:32

















          This is weird lib. It haven't online documentation. It haven't examples. It have problem with dependency (see your post with third party). And it's have problem with icon resize-load. I was led to a small amount of code and regretted it.

          – JayDi
          Nov 24 '17 at 12:32





          This is weird lib. It haven't online documentation. It haven't examples. It have problem with dependency (see your post with third party). And it's have problem with icon resize-load. I was led to a small amount of code and regretted it.

          – JayDi
          Nov 24 '17 at 12:32











          2














          This is what I use. It's an extension of BufferedImage with its own static factory that can be used wherever a BufferedImage is used. I wrote it so that any call to getScaledInstance(w, h, hint) will render from the SVG, not the rasterized image. A side-effect of this is that the scaling hint parameter has no meaning; you can just pass 0 or DEFAULT to that. It renders lazily - only when graphics data is requested - so the load / scale cycle shouldn't give you too much overhead.



          Edit: I added support using the above CSS config for scaling quality hints.
          Edit 2: Lazy rendering wasn't working consistently; I put the render() call into the constructor.



          It has the following dependencies:




          • org.apache.xmlgraphics:batik-anim

          • org.apache.xmlgraphics:batik-bridge

          • org.apache.xmlgraphics:batik-gvt

          • org.apache.xmlgraphics:batik-transcoder

          • org.apache.xmlgraphics:batik-util

          • xml-apis:xml-apis-ext

          • commons-logging:commons-logging


          When I made this, I used batik 1.8; YMMV.



          import java.awt.AlphaComposite;
          import java.awt.Composite;
          import java.awt.Graphics;
          import java.awt.Graphics2D;
          import java.awt.Image;
          import java.awt.image.BufferedImage;
          import java.awt.image.Raster;
          import java.awt.image.WritableRaster;
          import java.io.File;
          import java.io.FileWriter;
          import java.io.IOException;
          import java.io.InputStream;
          import java.net.URL;
          import java.util.HashMap;
          import java.util.Map;

          import org.apache.batik.anim.dom.SAXSVGDocumentFactory;
          import org.apache.batik.bridge.BridgeContext;
          import org.apache.batik.bridge.DocumentLoader;
          import org.apache.batik.bridge.GVTBuilder;
          import org.apache.batik.bridge.UserAgent;
          import org.apache.batik.bridge.UserAgentAdapter;
          import org.apache.batik.gvt.GraphicsNode;
          import org.apache.batik.transcoder.TranscoderException;
          import org.apache.batik.transcoder.TranscoderInput;
          import org.apache.batik.transcoder.TranscoderOutput;
          import org.apache.batik.transcoder.TranscodingHints;
          import org.apache.batik.transcoder.image.ImageTranscoder;
          import org.apache.batik.util.SVGConstants;
          import org.apache.batik.util.XMLResourceDescriptor;
          import org.apache.commons.logging.Log;
          import org.apache.commons.logging.LogFactory;
          import org.w3c.dom.svg.SVGDocument;

          public class SVGImage extends BufferedImage {
          private static class BufferedImageTranscoder extends ImageTranscoder {
          private BufferedImage image = null;
          @Override
          public BufferedImage createImage(int arg0, int arg1) {

          return image;
          }
          private void setImage(BufferedImage image) {
          this.image = image;
          }
          @Override
          public void writeImage(BufferedImage arg0, TranscoderOutput arg1) throws TranscoderException {
          }
          }

          final static GVTBuilder builder = new GVTBuilder();
          final static SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(XMLResourceDescriptor.getXMLParserClassName());
          final static UserAgent userAgent = new UserAgentAdapter();
          final static DocumentLoader loader = new DocumentLoader(userAgent);
          final static BridgeContext bridgeContext = new BridgeContext(userAgent, loader);
          static {
          bridgeContext.setDynamicState(BridgeContext.STATIC);
          }
          final static private Log log = LogFactory.getLog(SVGImage.class);
          private static final Map<Integer, String> scaleQuality = new HashMap<Integer, String>();
          static {
          String css = "svg {" +
          "shape-rendering: %s;" +
          "text-rendering: %s;" +
          "color-rendering: %s;" +
          "image-rendering: %s;" +
          "}";
          String precise = "geometricPrecision";
          String quality = "optimizeQuality";
          String speed = "optimizeSpeed";
          String crisp = "crispEdges";
          String legible = "optimizeLegibility";
          String auto = "auto";

          scaleQuality.put(SCALE_DEFAULT, String.format(css, auto, auto, auto, auto));
          scaleQuality.put(SCALE_SMOOTH, String.format(css, precise, precise, quality, quality));
          scaleQuality.put(SCALE_REPLICATE, String.format(css, speed, speed, speed, speed));
          scaleQuality.put(SCALE_AREA_AVERAGING, String.format(css, crisp, legible, auto, auto));
          scaleQuality.put(SCALE_FAST, String.format(css, speed, speed, speed, speed));
          }
          final static BufferedImageTranscoder transcoder = new BufferedImageTranscoder();

          public static SVGImage fromSvg(URL resource) throws IOException {
          InputStream rs = null;
          try {
          rs = resource.openStream();
          SVGDocument svg = factory.createSVGDocument(resource.toString(), rs);
          return fromSvgDocument(resource, svg);
          } finally {
          if (rs != null) {
          try { rs.close(); } catch (IOException ioe) {}
          }
          }
          }
          public static SVGImage fromSvgDocument(URL resource, SVGDocument doc) {
          GraphicsNode graphicsNode = builder.build(bridgeContext, doc);
          Double width = graphicsNode.getBounds().getWidth();
          Double height = graphicsNode.getBounds().getHeight();
          return new SVGImage(resource, doc, width.intValue(), height.intValue(), SCALE_DEFAULT);
          }
          boolean hasRendered = false;
          private int scalingHint = SCALE_DEFAULT;
          final SVGDocument svg;
          final URL svgUrl;
          private SVGImage(URL resource, SVGDocument doc, int width, int height, int hints) {
          super(width, height, TYPE_INT_ARGB);
          scalingHint = hints;
          svgUrl = resource;
          svg = doc;
          render();
          }
          @Override
          public void coerceData(boolean isAlphaPremultiplied) {
          if (!hasRendered) { render(); }
          super.coerceData(isAlphaPremultiplied);
          }
          @Override
          public WritableRaster copyData(WritableRaster outRaster) {
          if (!hasRendered) { render(); }
          return super.copyData(outRaster);
          }
          private File createCSS(String css) {
          FileWriter cssWriter = null;
          File cssFile = null;
          try {
          cssFile = File.createTempFile("batik-default-override-", ".css");
          cssFile.deleteOnExit();
          cssWriter = new FileWriter(cssFile);
          cssWriter.write(css);
          } catch(IOException ioe) {
          log.warn("Couldn't write stylesheet; SVG rendered with Batik defaults");
          } finally {

          if (cssWriter != null) {
          try {
          cssWriter.flush();
          cssWriter.close();
          } catch (IOException ioe) {}
          }
          }
          return cssFile;
          }
          @Override
          public WritableRaster getAlphaRaster() {
          if (!hasRendered) { render(); }
          return super.getAlphaRaster();
          }
          @Override
          public Raster getData() {
          if (!hasRendered) { render(); }
          return super.getData();
          }

          @Override
          public Graphics getGraphics() {
          if (!hasRendered) { render(); }
          return super.getGraphics();
          }
          public Image getScaledInstance(int width, int height, int hints) {
          SVGImage newImage = new SVGImage(svgUrl, svg, width, height, hints);
          return newImage;
          }
          private void render() {
          TranscodingHints hints = new TranscodingHints();
          hints.put(ImageTranscoder.KEY_WIDTH, new Float(getWidth()));
          hints.put(ImageTranscoder.KEY_HEIGHT, new Float(getHeight()));
          hints.put(ImageTranscoder.KEY_XML_PARSER_VALIDATING, Boolean.FALSE);
          hints.put(ImageTranscoder.KEY_DOM_IMPLEMENTATION, svg.getImplementation());
          hints.put(ImageTranscoder.KEY_DOCUMENT_ELEMENT_NAMESPACE_URI, SVGConstants.SVG_NAMESPACE_URI);
          hints.put(ImageTranscoder.KEY_DOCUMENT_ELEMENT, "svg");
          String css = scaleQuality.get(scalingHint);
          File cssFile = null;
          if (css != null) {
          cssFile = createCSS(css);
          if (cssFile != null) {
          hints.put(ImageTranscoder.KEY_USER_STYLESHEET_URI, cssFile.toURI().toString());
          }
          }
          transcoder.setTranscodingHints(hints);
          transcoder.setImage(this);
          // This may be a re-render, if the scaling quality hint has changed.
          // As such, we force the image into overwrite mode, and kick it back when we're done / fail
          Graphics2D gfx = (Graphics2D) super.getGraphics();
          Composite savedComposite = gfx.getComposite();
          gfx.setComposite(AlphaComposite.Clear);
          try {
          transcoder.transcode(new TranscoderInput(svg), null);
          hasRendered = true;
          } catch (TranscoderException te) {
          log.warn("Could not transcode " + svgUrl.getPath() + " to raster image; you're going to get a blank BufferedImage of the correct size.");
          } finally {
          gfx.setComposite(savedComposite);
          if (cssFile != null) {
          cssFile.delete();
          }
          }
          }
          public void setScalingHint(int hint) {
          this.scalingHint = hint;
          // Forces a re-render
          this.hasRendered = false;
          }
          }





          share|improve this answer


























          • Incidentally, I think I'll be stealing the CSS transcoder hint above to emulate the scaling hints from BufferedImage.

            – Fordi
            Jun 14 '15 at 5:43
















          2














          This is what I use. It's an extension of BufferedImage with its own static factory that can be used wherever a BufferedImage is used. I wrote it so that any call to getScaledInstance(w, h, hint) will render from the SVG, not the rasterized image. A side-effect of this is that the scaling hint parameter has no meaning; you can just pass 0 or DEFAULT to that. It renders lazily - only when graphics data is requested - so the load / scale cycle shouldn't give you too much overhead.



          Edit: I added support using the above CSS config for scaling quality hints.
          Edit 2: Lazy rendering wasn't working consistently; I put the render() call into the constructor.



          It has the following dependencies:




          • org.apache.xmlgraphics:batik-anim

          • org.apache.xmlgraphics:batik-bridge

          • org.apache.xmlgraphics:batik-gvt

          • org.apache.xmlgraphics:batik-transcoder

          • org.apache.xmlgraphics:batik-util

          • xml-apis:xml-apis-ext

          • commons-logging:commons-logging


          When I made this, I used batik 1.8; YMMV.



          import java.awt.AlphaComposite;
          import java.awt.Composite;
          import java.awt.Graphics;
          import java.awt.Graphics2D;
          import java.awt.Image;
          import java.awt.image.BufferedImage;
          import java.awt.image.Raster;
          import java.awt.image.WritableRaster;
          import java.io.File;
          import java.io.FileWriter;
          import java.io.IOException;
          import java.io.InputStream;
          import java.net.URL;
          import java.util.HashMap;
          import java.util.Map;

          import org.apache.batik.anim.dom.SAXSVGDocumentFactory;
          import org.apache.batik.bridge.BridgeContext;
          import org.apache.batik.bridge.DocumentLoader;
          import org.apache.batik.bridge.GVTBuilder;
          import org.apache.batik.bridge.UserAgent;
          import org.apache.batik.bridge.UserAgentAdapter;
          import org.apache.batik.gvt.GraphicsNode;
          import org.apache.batik.transcoder.TranscoderException;
          import org.apache.batik.transcoder.TranscoderInput;
          import org.apache.batik.transcoder.TranscoderOutput;
          import org.apache.batik.transcoder.TranscodingHints;
          import org.apache.batik.transcoder.image.ImageTranscoder;
          import org.apache.batik.util.SVGConstants;
          import org.apache.batik.util.XMLResourceDescriptor;
          import org.apache.commons.logging.Log;
          import org.apache.commons.logging.LogFactory;
          import org.w3c.dom.svg.SVGDocument;

          public class SVGImage extends BufferedImage {
          private static class BufferedImageTranscoder extends ImageTranscoder {
          private BufferedImage image = null;
          @Override
          public BufferedImage createImage(int arg0, int arg1) {

          return image;
          }
          private void setImage(BufferedImage image) {
          this.image = image;
          }
          @Override
          public void writeImage(BufferedImage arg0, TranscoderOutput arg1) throws TranscoderException {
          }
          }

          final static GVTBuilder builder = new GVTBuilder();
          final static SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(XMLResourceDescriptor.getXMLParserClassName());
          final static UserAgent userAgent = new UserAgentAdapter();
          final static DocumentLoader loader = new DocumentLoader(userAgent);
          final static BridgeContext bridgeContext = new BridgeContext(userAgent, loader);
          static {
          bridgeContext.setDynamicState(BridgeContext.STATIC);
          }
          final static private Log log = LogFactory.getLog(SVGImage.class);
          private static final Map<Integer, String> scaleQuality = new HashMap<Integer, String>();
          static {
          String css = "svg {" +
          "shape-rendering: %s;" +
          "text-rendering: %s;" +
          "color-rendering: %s;" +
          "image-rendering: %s;" +
          "}";
          String precise = "geometricPrecision";
          String quality = "optimizeQuality";
          String speed = "optimizeSpeed";
          String crisp = "crispEdges";
          String legible = "optimizeLegibility";
          String auto = "auto";

          scaleQuality.put(SCALE_DEFAULT, String.format(css, auto, auto, auto, auto));
          scaleQuality.put(SCALE_SMOOTH, String.format(css, precise, precise, quality, quality));
          scaleQuality.put(SCALE_REPLICATE, String.format(css, speed, speed, speed, speed));
          scaleQuality.put(SCALE_AREA_AVERAGING, String.format(css, crisp, legible, auto, auto));
          scaleQuality.put(SCALE_FAST, String.format(css, speed, speed, speed, speed));
          }
          final static BufferedImageTranscoder transcoder = new BufferedImageTranscoder();

          public static SVGImage fromSvg(URL resource) throws IOException {
          InputStream rs = null;
          try {
          rs = resource.openStream();
          SVGDocument svg = factory.createSVGDocument(resource.toString(), rs);
          return fromSvgDocument(resource, svg);
          } finally {
          if (rs != null) {
          try { rs.close(); } catch (IOException ioe) {}
          }
          }
          }
          public static SVGImage fromSvgDocument(URL resource, SVGDocument doc) {
          GraphicsNode graphicsNode = builder.build(bridgeContext, doc);
          Double width = graphicsNode.getBounds().getWidth();
          Double height = graphicsNode.getBounds().getHeight();
          return new SVGImage(resource, doc, width.intValue(), height.intValue(), SCALE_DEFAULT);
          }
          boolean hasRendered = false;
          private int scalingHint = SCALE_DEFAULT;
          final SVGDocument svg;
          final URL svgUrl;
          private SVGImage(URL resource, SVGDocument doc, int width, int height, int hints) {
          super(width, height, TYPE_INT_ARGB);
          scalingHint = hints;
          svgUrl = resource;
          svg = doc;
          render();
          }
          @Override
          public void coerceData(boolean isAlphaPremultiplied) {
          if (!hasRendered) { render(); }
          super.coerceData(isAlphaPremultiplied);
          }
          @Override
          public WritableRaster copyData(WritableRaster outRaster) {
          if (!hasRendered) { render(); }
          return super.copyData(outRaster);
          }
          private File createCSS(String css) {
          FileWriter cssWriter = null;
          File cssFile = null;
          try {
          cssFile = File.createTempFile("batik-default-override-", ".css");
          cssFile.deleteOnExit();
          cssWriter = new FileWriter(cssFile);
          cssWriter.write(css);
          } catch(IOException ioe) {
          log.warn("Couldn't write stylesheet; SVG rendered with Batik defaults");
          } finally {

          if (cssWriter != null) {
          try {
          cssWriter.flush();
          cssWriter.close();
          } catch (IOException ioe) {}
          }
          }
          return cssFile;
          }
          @Override
          public WritableRaster getAlphaRaster() {
          if (!hasRendered) { render(); }
          return super.getAlphaRaster();
          }
          @Override
          public Raster getData() {
          if (!hasRendered) { render(); }
          return super.getData();
          }

          @Override
          public Graphics getGraphics() {
          if (!hasRendered) { render(); }
          return super.getGraphics();
          }
          public Image getScaledInstance(int width, int height, int hints) {
          SVGImage newImage = new SVGImage(svgUrl, svg, width, height, hints);
          return newImage;
          }
          private void render() {
          TranscodingHints hints = new TranscodingHints();
          hints.put(ImageTranscoder.KEY_WIDTH, new Float(getWidth()));
          hints.put(ImageTranscoder.KEY_HEIGHT, new Float(getHeight()));
          hints.put(ImageTranscoder.KEY_XML_PARSER_VALIDATING, Boolean.FALSE);
          hints.put(ImageTranscoder.KEY_DOM_IMPLEMENTATION, svg.getImplementation());
          hints.put(ImageTranscoder.KEY_DOCUMENT_ELEMENT_NAMESPACE_URI, SVGConstants.SVG_NAMESPACE_URI);
          hints.put(ImageTranscoder.KEY_DOCUMENT_ELEMENT, "svg");
          String css = scaleQuality.get(scalingHint);
          File cssFile = null;
          if (css != null) {
          cssFile = createCSS(css);
          if (cssFile != null) {
          hints.put(ImageTranscoder.KEY_USER_STYLESHEET_URI, cssFile.toURI().toString());
          }
          }
          transcoder.setTranscodingHints(hints);
          transcoder.setImage(this);
          // This may be a re-render, if the scaling quality hint has changed.
          // As such, we force the image into overwrite mode, and kick it back when we're done / fail
          Graphics2D gfx = (Graphics2D) super.getGraphics();
          Composite savedComposite = gfx.getComposite();
          gfx.setComposite(AlphaComposite.Clear);
          try {
          transcoder.transcode(new TranscoderInput(svg), null);
          hasRendered = true;
          } catch (TranscoderException te) {
          log.warn("Could not transcode " + svgUrl.getPath() + " to raster image; you're going to get a blank BufferedImage of the correct size.");
          } finally {
          gfx.setComposite(savedComposite);
          if (cssFile != null) {
          cssFile.delete();
          }
          }
          }
          public void setScalingHint(int hint) {
          this.scalingHint = hint;
          // Forces a re-render
          this.hasRendered = false;
          }
          }





          share|improve this answer


























          • Incidentally, I think I'll be stealing the CSS transcoder hint above to emulate the scaling hints from BufferedImage.

            – Fordi
            Jun 14 '15 at 5:43














          2












          2








          2







          This is what I use. It's an extension of BufferedImage with its own static factory that can be used wherever a BufferedImage is used. I wrote it so that any call to getScaledInstance(w, h, hint) will render from the SVG, not the rasterized image. A side-effect of this is that the scaling hint parameter has no meaning; you can just pass 0 or DEFAULT to that. It renders lazily - only when graphics data is requested - so the load / scale cycle shouldn't give you too much overhead.



          Edit: I added support using the above CSS config for scaling quality hints.
          Edit 2: Lazy rendering wasn't working consistently; I put the render() call into the constructor.



          It has the following dependencies:




          • org.apache.xmlgraphics:batik-anim

          • org.apache.xmlgraphics:batik-bridge

          • org.apache.xmlgraphics:batik-gvt

          • org.apache.xmlgraphics:batik-transcoder

          • org.apache.xmlgraphics:batik-util

          • xml-apis:xml-apis-ext

          • commons-logging:commons-logging


          When I made this, I used batik 1.8; YMMV.



          import java.awt.AlphaComposite;
          import java.awt.Composite;
          import java.awt.Graphics;
          import java.awt.Graphics2D;
          import java.awt.Image;
          import java.awt.image.BufferedImage;
          import java.awt.image.Raster;
          import java.awt.image.WritableRaster;
          import java.io.File;
          import java.io.FileWriter;
          import java.io.IOException;
          import java.io.InputStream;
          import java.net.URL;
          import java.util.HashMap;
          import java.util.Map;

          import org.apache.batik.anim.dom.SAXSVGDocumentFactory;
          import org.apache.batik.bridge.BridgeContext;
          import org.apache.batik.bridge.DocumentLoader;
          import org.apache.batik.bridge.GVTBuilder;
          import org.apache.batik.bridge.UserAgent;
          import org.apache.batik.bridge.UserAgentAdapter;
          import org.apache.batik.gvt.GraphicsNode;
          import org.apache.batik.transcoder.TranscoderException;
          import org.apache.batik.transcoder.TranscoderInput;
          import org.apache.batik.transcoder.TranscoderOutput;
          import org.apache.batik.transcoder.TranscodingHints;
          import org.apache.batik.transcoder.image.ImageTranscoder;
          import org.apache.batik.util.SVGConstants;
          import org.apache.batik.util.XMLResourceDescriptor;
          import org.apache.commons.logging.Log;
          import org.apache.commons.logging.LogFactory;
          import org.w3c.dom.svg.SVGDocument;

          public class SVGImage extends BufferedImage {
          private static class BufferedImageTranscoder extends ImageTranscoder {
          private BufferedImage image = null;
          @Override
          public BufferedImage createImage(int arg0, int arg1) {

          return image;
          }
          private void setImage(BufferedImage image) {
          this.image = image;
          }
          @Override
          public void writeImage(BufferedImage arg0, TranscoderOutput arg1) throws TranscoderException {
          }
          }

          final static GVTBuilder builder = new GVTBuilder();
          final static SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(XMLResourceDescriptor.getXMLParserClassName());
          final static UserAgent userAgent = new UserAgentAdapter();
          final static DocumentLoader loader = new DocumentLoader(userAgent);
          final static BridgeContext bridgeContext = new BridgeContext(userAgent, loader);
          static {
          bridgeContext.setDynamicState(BridgeContext.STATIC);
          }
          final static private Log log = LogFactory.getLog(SVGImage.class);
          private static final Map<Integer, String> scaleQuality = new HashMap<Integer, String>();
          static {
          String css = "svg {" +
          "shape-rendering: %s;" +
          "text-rendering: %s;" +
          "color-rendering: %s;" +
          "image-rendering: %s;" +
          "}";
          String precise = "geometricPrecision";
          String quality = "optimizeQuality";
          String speed = "optimizeSpeed";
          String crisp = "crispEdges";
          String legible = "optimizeLegibility";
          String auto = "auto";

          scaleQuality.put(SCALE_DEFAULT, String.format(css, auto, auto, auto, auto));
          scaleQuality.put(SCALE_SMOOTH, String.format(css, precise, precise, quality, quality));
          scaleQuality.put(SCALE_REPLICATE, String.format(css, speed, speed, speed, speed));
          scaleQuality.put(SCALE_AREA_AVERAGING, String.format(css, crisp, legible, auto, auto));
          scaleQuality.put(SCALE_FAST, String.format(css, speed, speed, speed, speed));
          }
          final static BufferedImageTranscoder transcoder = new BufferedImageTranscoder();

          public static SVGImage fromSvg(URL resource) throws IOException {
          InputStream rs = null;
          try {
          rs = resource.openStream();
          SVGDocument svg = factory.createSVGDocument(resource.toString(), rs);
          return fromSvgDocument(resource, svg);
          } finally {
          if (rs != null) {
          try { rs.close(); } catch (IOException ioe) {}
          }
          }
          }
          public static SVGImage fromSvgDocument(URL resource, SVGDocument doc) {
          GraphicsNode graphicsNode = builder.build(bridgeContext, doc);
          Double width = graphicsNode.getBounds().getWidth();
          Double height = graphicsNode.getBounds().getHeight();
          return new SVGImage(resource, doc, width.intValue(), height.intValue(), SCALE_DEFAULT);
          }
          boolean hasRendered = false;
          private int scalingHint = SCALE_DEFAULT;
          final SVGDocument svg;
          final URL svgUrl;
          private SVGImage(URL resource, SVGDocument doc, int width, int height, int hints) {
          super(width, height, TYPE_INT_ARGB);
          scalingHint = hints;
          svgUrl = resource;
          svg = doc;
          render();
          }
          @Override
          public void coerceData(boolean isAlphaPremultiplied) {
          if (!hasRendered) { render(); }
          super.coerceData(isAlphaPremultiplied);
          }
          @Override
          public WritableRaster copyData(WritableRaster outRaster) {
          if (!hasRendered) { render(); }
          return super.copyData(outRaster);
          }
          private File createCSS(String css) {
          FileWriter cssWriter = null;
          File cssFile = null;
          try {
          cssFile = File.createTempFile("batik-default-override-", ".css");
          cssFile.deleteOnExit();
          cssWriter = new FileWriter(cssFile);
          cssWriter.write(css);
          } catch(IOException ioe) {
          log.warn("Couldn't write stylesheet; SVG rendered with Batik defaults");
          } finally {

          if (cssWriter != null) {
          try {
          cssWriter.flush();
          cssWriter.close();
          } catch (IOException ioe) {}
          }
          }
          return cssFile;
          }
          @Override
          public WritableRaster getAlphaRaster() {
          if (!hasRendered) { render(); }
          return super.getAlphaRaster();
          }
          @Override
          public Raster getData() {
          if (!hasRendered) { render(); }
          return super.getData();
          }

          @Override
          public Graphics getGraphics() {
          if (!hasRendered) { render(); }
          return super.getGraphics();
          }
          public Image getScaledInstance(int width, int height, int hints) {
          SVGImage newImage = new SVGImage(svgUrl, svg, width, height, hints);
          return newImage;
          }
          private void render() {
          TranscodingHints hints = new TranscodingHints();
          hints.put(ImageTranscoder.KEY_WIDTH, new Float(getWidth()));
          hints.put(ImageTranscoder.KEY_HEIGHT, new Float(getHeight()));
          hints.put(ImageTranscoder.KEY_XML_PARSER_VALIDATING, Boolean.FALSE);
          hints.put(ImageTranscoder.KEY_DOM_IMPLEMENTATION, svg.getImplementation());
          hints.put(ImageTranscoder.KEY_DOCUMENT_ELEMENT_NAMESPACE_URI, SVGConstants.SVG_NAMESPACE_URI);
          hints.put(ImageTranscoder.KEY_DOCUMENT_ELEMENT, "svg");
          String css = scaleQuality.get(scalingHint);
          File cssFile = null;
          if (css != null) {
          cssFile = createCSS(css);
          if (cssFile != null) {
          hints.put(ImageTranscoder.KEY_USER_STYLESHEET_URI, cssFile.toURI().toString());
          }
          }
          transcoder.setTranscodingHints(hints);
          transcoder.setImage(this);
          // This may be a re-render, if the scaling quality hint has changed.
          // As such, we force the image into overwrite mode, and kick it back when we're done / fail
          Graphics2D gfx = (Graphics2D) super.getGraphics();
          Composite savedComposite = gfx.getComposite();
          gfx.setComposite(AlphaComposite.Clear);
          try {
          transcoder.transcode(new TranscoderInput(svg), null);
          hasRendered = true;
          } catch (TranscoderException te) {
          log.warn("Could not transcode " + svgUrl.getPath() + " to raster image; you're going to get a blank BufferedImage of the correct size.");
          } finally {
          gfx.setComposite(savedComposite);
          if (cssFile != null) {
          cssFile.delete();
          }
          }
          }
          public void setScalingHint(int hint) {
          this.scalingHint = hint;
          // Forces a re-render
          this.hasRendered = false;
          }
          }





          share|improve this answer















          This is what I use. It's an extension of BufferedImage with its own static factory that can be used wherever a BufferedImage is used. I wrote it so that any call to getScaledInstance(w, h, hint) will render from the SVG, not the rasterized image. A side-effect of this is that the scaling hint parameter has no meaning; you can just pass 0 or DEFAULT to that. It renders lazily - only when graphics data is requested - so the load / scale cycle shouldn't give you too much overhead.



          Edit: I added support using the above CSS config for scaling quality hints.
          Edit 2: Lazy rendering wasn't working consistently; I put the render() call into the constructor.



          It has the following dependencies:




          • org.apache.xmlgraphics:batik-anim

          • org.apache.xmlgraphics:batik-bridge

          • org.apache.xmlgraphics:batik-gvt

          • org.apache.xmlgraphics:batik-transcoder

          • org.apache.xmlgraphics:batik-util

          • xml-apis:xml-apis-ext

          • commons-logging:commons-logging


          When I made this, I used batik 1.8; YMMV.



          import java.awt.AlphaComposite;
          import java.awt.Composite;
          import java.awt.Graphics;
          import java.awt.Graphics2D;
          import java.awt.Image;
          import java.awt.image.BufferedImage;
          import java.awt.image.Raster;
          import java.awt.image.WritableRaster;
          import java.io.File;
          import java.io.FileWriter;
          import java.io.IOException;
          import java.io.InputStream;
          import java.net.URL;
          import java.util.HashMap;
          import java.util.Map;

          import org.apache.batik.anim.dom.SAXSVGDocumentFactory;
          import org.apache.batik.bridge.BridgeContext;
          import org.apache.batik.bridge.DocumentLoader;
          import org.apache.batik.bridge.GVTBuilder;
          import org.apache.batik.bridge.UserAgent;
          import org.apache.batik.bridge.UserAgentAdapter;
          import org.apache.batik.gvt.GraphicsNode;
          import org.apache.batik.transcoder.TranscoderException;
          import org.apache.batik.transcoder.TranscoderInput;
          import org.apache.batik.transcoder.TranscoderOutput;
          import org.apache.batik.transcoder.TranscodingHints;
          import org.apache.batik.transcoder.image.ImageTranscoder;
          import org.apache.batik.util.SVGConstants;
          import org.apache.batik.util.XMLResourceDescriptor;
          import org.apache.commons.logging.Log;
          import org.apache.commons.logging.LogFactory;
          import org.w3c.dom.svg.SVGDocument;

          public class SVGImage extends BufferedImage {
          private static class BufferedImageTranscoder extends ImageTranscoder {
          private BufferedImage image = null;
          @Override
          public BufferedImage createImage(int arg0, int arg1) {

          return image;
          }
          private void setImage(BufferedImage image) {
          this.image = image;
          }
          @Override
          public void writeImage(BufferedImage arg0, TranscoderOutput arg1) throws TranscoderException {
          }
          }

          final static GVTBuilder builder = new GVTBuilder();
          final static SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(XMLResourceDescriptor.getXMLParserClassName());
          final static UserAgent userAgent = new UserAgentAdapter();
          final static DocumentLoader loader = new DocumentLoader(userAgent);
          final static BridgeContext bridgeContext = new BridgeContext(userAgent, loader);
          static {
          bridgeContext.setDynamicState(BridgeContext.STATIC);
          }
          final static private Log log = LogFactory.getLog(SVGImage.class);
          private static final Map<Integer, String> scaleQuality = new HashMap<Integer, String>();
          static {
          String css = "svg {" +
          "shape-rendering: %s;" +
          "text-rendering: %s;" +
          "color-rendering: %s;" +
          "image-rendering: %s;" +
          "}";
          String precise = "geometricPrecision";
          String quality = "optimizeQuality";
          String speed = "optimizeSpeed";
          String crisp = "crispEdges";
          String legible = "optimizeLegibility";
          String auto = "auto";

          scaleQuality.put(SCALE_DEFAULT, String.format(css, auto, auto, auto, auto));
          scaleQuality.put(SCALE_SMOOTH, String.format(css, precise, precise, quality, quality));
          scaleQuality.put(SCALE_REPLICATE, String.format(css, speed, speed, speed, speed));
          scaleQuality.put(SCALE_AREA_AVERAGING, String.format(css, crisp, legible, auto, auto));
          scaleQuality.put(SCALE_FAST, String.format(css, speed, speed, speed, speed));
          }
          final static BufferedImageTranscoder transcoder = new BufferedImageTranscoder();

          public static SVGImage fromSvg(URL resource) throws IOException {
          InputStream rs = null;
          try {
          rs = resource.openStream();
          SVGDocument svg = factory.createSVGDocument(resource.toString(), rs);
          return fromSvgDocument(resource, svg);
          } finally {
          if (rs != null) {
          try { rs.close(); } catch (IOException ioe) {}
          }
          }
          }
          public static SVGImage fromSvgDocument(URL resource, SVGDocument doc) {
          GraphicsNode graphicsNode = builder.build(bridgeContext, doc);
          Double width = graphicsNode.getBounds().getWidth();
          Double height = graphicsNode.getBounds().getHeight();
          return new SVGImage(resource, doc, width.intValue(), height.intValue(), SCALE_DEFAULT);
          }
          boolean hasRendered = false;
          private int scalingHint = SCALE_DEFAULT;
          final SVGDocument svg;
          final URL svgUrl;
          private SVGImage(URL resource, SVGDocument doc, int width, int height, int hints) {
          super(width, height, TYPE_INT_ARGB);
          scalingHint = hints;
          svgUrl = resource;
          svg = doc;
          render();
          }
          @Override
          public void coerceData(boolean isAlphaPremultiplied) {
          if (!hasRendered) { render(); }
          super.coerceData(isAlphaPremultiplied);
          }
          @Override
          public WritableRaster copyData(WritableRaster outRaster) {
          if (!hasRendered) { render(); }
          return super.copyData(outRaster);
          }
          private File createCSS(String css) {
          FileWriter cssWriter = null;
          File cssFile = null;
          try {
          cssFile = File.createTempFile("batik-default-override-", ".css");
          cssFile.deleteOnExit();
          cssWriter = new FileWriter(cssFile);
          cssWriter.write(css);
          } catch(IOException ioe) {
          log.warn("Couldn't write stylesheet; SVG rendered with Batik defaults");
          } finally {

          if (cssWriter != null) {
          try {
          cssWriter.flush();
          cssWriter.close();
          } catch (IOException ioe) {}
          }
          }
          return cssFile;
          }
          @Override
          public WritableRaster getAlphaRaster() {
          if (!hasRendered) { render(); }
          return super.getAlphaRaster();
          }
          @Override
          public Raster getData() {
          if (!hasRendered) { render(); }
          return super.getData();
          }

          @Override
          public Graphics getGraphics() {
          if (!hasRendered) { render(); }
          return super.getGraphics();
          }
          public Image getScaledInstance(int width, int height, int hints) {
          SVGImage newImage = new SVGImage(svgUrl, svg, width, height, hints);
          return newImage;
          }
          private void render() {
          TranscodingHints hints = new TranscodingHints();
          hints.put(ImageTranscoder.KEY_WIDTH, new Float(getWidth()));
          hints.put(ImageTranscoder.KEY_HEIGHT, new Float(getHeight()));
          hints.put(ImageTranscoder.KEY_XML_PARSER_VALIDATING, Boolean.FALSE);
          hints.put(ImageTranscoder.KEY_DOM_IMPLEMENTATION, svg.getImplementation());
          hints.put(ImageTranscoder.KEY_DOCUMENT_ELEMENT_NAMESPACE_URI, SVGConstants.SVG_NAMESPACE_URI);
          hints.put(ImageTranscoder.KEY_DOCUMENT_ELEMENT, "svg");
          String css = scaleQuality.get(scalingHint);
          File cssFile = null;
          if (css != null) {
          cssFile = createCSS(css);
          if (cssFile != null) {
          hints.put(ImageTranscoder.KEY_USER_STYLESHEET_URI, cssFile.toURI().toString());
          }
          }
          transcoder.setTranscodingHints(hints);
          transcoder.setImage(this);
          // This may be a re-render, if the scaling quality hint has changed.
          // As such, we force the image into overwrite mode, and kick it back when we're done / fail
          Graphics2D gfx = (Graphics2D) super.getGraphics();
          Composite savedComposite = gfx.getComposite();
          gfx.setComposite(AlphaComposite.Clear);
          try {
          transcoder.transcode(new TranscoderInput(svg), null);
          hasRendered = true;
          } catch (TranscoderException te) {
          log.warn("Could not transcode " + svgUrl.getPath() + " to raster image; you're going to get a blank BufferedImage of the correct size.");
          } finally {
          gfx.setComposite(savedComposite);
          if (cssFile != null) {
          cssFile.delete();
          }
          }
          }
          public void setScalingHint(int hint) {
          this.scalingHint = hint;
          // Forces a re-render
          this.hasRendered = false;
          }
          }






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Jun 14 '15 at 6:41

























          answered Jun 14 '15 at 5:42









          FordiFordi

          2,0911819




          2,0911819













          • Incidentally, I think I'll be stealing the CSS transcoder hint above to emulate the scaling hints from BufferedImage.

            – Fordi
            Jun 14 '15 at 5:43



















          • Incidentally, I think I'll be stealing the CSS transcoder hint above to emulate the scaling hints from BufferedImage.

            – Fordi
            Jun 14 '15 at 5:43

















          Incidentally, I think I'll be stealing the CSS transcoder hint above to emulate the scaling hints from BufferedImage.

          – Fordi
          Jun 14 '15 at 5:43





          Incidentally, I think I'll be stealing the CSS transcoder hint above to emulate the scaling hints from BufferedImage.

          – Fordi
          Jun 14 '15 at 5:43


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f11435671%2fhow-to-get-a-bufferedimage-from-a-svg%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Xamarin.iOS Cant Deploy on Iphone

          Glorious Revolution

          Dulmage-Mendelsohn matrix decomposition in Python