Swing & Batik:从 SVG 文件创建 ImageIcon?

问题描述 投票:0回答:4

简而言之,我正在寻找一种使用 batik 库从 SVG 文件制作 ImageIcon 的方法。我不想先将 SVG 光栅化到磁盘,我只想能够从 jar 文件中提取 svg 并将其作为 UI 元素放置。

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

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

java swing svg icons batik
4个回答
24
投票

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

你需要延长

ImageTranscoder
。在
createImage
方法中,您分配一个
BufferedImage
,将其缓存为成员变量,然后返回它。
writeImage
方法是空的。你需要添加一个吸气剂来检索
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 周的时间就弄明白了。唉。)


3
投票

我刚刚使用 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.


1
投票

我尝试使用 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;
    }
  }
}

0
投票

为了避免传递dom参数:


    transcoder.setTranscodingHints((Map<?, ?>) hints);

© www.soinside.com 2019 - 2024. All rights reserved.