【问题标题】:Swing & Batik: Create an ImageIcon from an SVG file?Swing & Batik:从 SVG 文件创建 ImageIcon?
【发布时间】:2011-01-30 12:44:23
【问题描述】:

简单地说,我正在寻找一种使用蜡染库从 SVG 文件制作 ImageIcon 的方法。我不想先将 SVG 光栅化到磁盘,我只想能够从 jar 文件中提取一个 svg 并将其作为 UI 元素着陆。

我觉得这应该相当容易,但蜡染 javadocs 并没有告诉我我需要知道什么。

(为什么是蜡染?好吧,我们已经在使用它了,所以我们不必再运行一个合法的库。)

【问题讨论】:

    标签: java swing svg icons batik


    【解决方案1】:

    这真的很简单,只是不太直观。

    您需要扩展ImageTranscoder。在createImage 方法中,您分配一个BufferedImage,将其缓存为成员变量,然后将其返回。 writeImage 方法为空。您需要添加一个 getter 来检索 BufferedImage

    它看起来像这样:

        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;
            }
        }
    

    现在,要创建图像,您需要创建转码器实例,并通过设置TranscodingHints 为其传递所需的宽度和高度。最后,您从 TranscoderInput 转码为空目标。然后调用转码器上的 getter 来获取图像。

    调用看起来像这样:

        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();
    

    很简单,对吧? (是的,没错。我只花了 2 周时间就弄清楚了。叹息。)

    【讨论】:

    • 是的,Devon 说的。 :) 这是我的 SVGIcon 类,它几乎可以做到这一点:mcc.id.au/2005/04/SVGIcon.java
    • 很高兴知道这些类应该在哪个包中。
    • @mmm 已经有一段时间了,但它应该类似于org.apache.batik.transcoder 或它的子包。
    【解决方案2】:

    我刚刚在 Batik-1.7 上遵循了 Devon 的方法

    但是,为了使其正常工作,我必须在提示对象中添加以下内容:

    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();
    

    蜡染的 XMLAbstractTranscoder(http://svn.apache.org/repos/asf/xmlgraphics/batik/tags/batik-1_7/sources/org/apache/batik/transcoder/XMLAbstractTranscoder.java) 似乎更新了 1.7 版。

    【讨论】:

      【解决方案3】:

      如果您不再希望在应用程序中包含对 Batik 的依赖,您可以使用 Flamingo SVG 转码器将 SVG 文件直接转换为 Java2D:

      http://ebourg.github.com/flamingo-svg-transcoder

      它生成的图标类的大小与压缩的 SVG 文件大致相当。生成的代码没有外部依赖。

      【讨论】:

      • 要验证,您的答案是,与其尝试在运行时读取和呈现 svg(并包含所有依赖项),另一种方法是在编译时将 SVG 转码为类文件(仅构建系统需要蜡染)。然后类文件与应用程序一起打包。
      【解决方案4】:

      避免传递dom参数: transcoder.setTranscodingHints((Map<?, ?>) hints);

      【讨论】:

      • 这应该是@John Doppelmann 的评论吧?那么请不要“回答”它,如果可能,请使用 cmets。
      【解决方案5】:

      我尝试使用 Devon 和 John 的建议,这几乎对我有用。我不得不做一些调整如下,请随意使用:

      package com.corp.util;
      
      import static org.apache.batik.transcoder.SVGAbstractTranscoder.KEY_WIDTH;
      import static org.apache.batik.transcoder.XMLAbstractTranscoder.KEY_DOCUMENT_ELEMENT;
      import static org.apache.batik.transcoder.XMLAbstractTranscoder.KEY_DOCUMENT_ELEMENT_NAMESPACE_URI;
      import static org.apache.batik.transcoder.XMLAbstractTranscoder.KEY_DOM_IMPLEMENTATION;
      import static org.apache.batik.util.SVGConstants.SVG_NAMESPACE_URI;
      import static org.apache.batik.util.SVGConstants.SVG_SVG_TAG;
      
      import com.google.common.flogger.GoogleLogger;
      
      import org.apache.batik.anim.dom.SVGDOMImplementation;
      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 java.awt.image.BufferedImage;
      import java.io.File;
      import java.io.IOException;
      import java.net.URL;
      
      import javax.annotation.concurrent.ThreadSafe;
      import javax.inject.Singleton;
      
      /** Loads SVG images from disk. See https://en.wikipedia.org/wiki/Scalable_Vector_Graphics. */
      @Singleton
      @ThreadSafe
      public class SvgImageLoader {
      
        private static final GoogleLogger logger = GoogleLogger.forEnclosingClass();
      
        /**
         * Reads in an SVG image file and return it as a BufferedImage with the given width and a height
         * where the original aspect ratio is preserved.
         *
         * @param url URL referencing the SVG image file, which is typically an XML file
         * @param width width in pixels the returned BufferedImage should be
         *
         * @return a valid image representing the SVG file
         * @throws IOException if the file cannot be parsed as valid SVG
         */
        public static BufferedImage loadSvg(URL url, float width) throws IOException {
          SvgTranscoder transcoder = new SvgTranscoder();
          transcoder.setTranscodingHints(getHints(width));
          try {
            TranscoderInput input = new TranscoderInput(url.openStream());
            transcoder.transcode(input, null);
          } catch (TranscoderException e) {
            throw new IOException("Error parsing SVG file " + url, e);
          }
          BufferedImage image = transcoder.getImage();
          logger.atInfo().log("Read '%s' SVG image from disk requested with width=%.1f, sized as %dx%d pixels.",
              new File(url.getFile()).getName(), width, image.getWidth(), image.getHeight());
          return image;
        }
      
        private static TranscodingHints getHints(float width) {
          TranscodingHints hints = new TranscodingHints();
          hints.put(KEY_DOM_IMPLEMENTATION, SVGDOMImplementation.getDOMImplementation());
          hints.put(KEY_DOCUMENT_ELEMENT_NAMESPACE_URI, SVG_NAMESPACE_URI);
          hints.put(KEY_DOCUMENT_ELEMENT, SVG_SVG_TAG);
          hints.put(KEY_WIDTH, width);
          return hints;
        }
      
        private static class SvgTranscoder extends ImageTranscoder {
      
          private BufferedImage image = null;
      
          @Override
          public BufferedImage createImage(int width, int height) {
            image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
            return image;
          }
      
          @Override
          public void writeImage(BufferedImage img, TranscoderOutput out) {}
      
          BufferedImage getImage() {
            return image;
          }
        }
      }
      

      【讨论】:

        猜你喜欢
        • 2011-05-06
        • 1970-01-01
        • 2018-07-02
        • 2018-03-28
        • 2018-01-07
        • 2016-11-09
        • 1970-01-01
        • 2012-11-22
        • 2019-10-16
        相关资源
        最近更新 更多