Swing & Batik: создать ImageIcon из файла SVG? - PullRequest
17 голосов
/ 22 марта 2010

Проще говоря, я ищу способ сделать ImageIcon из файла SVG, используя библиотеку батика. Я не хочу сначала растрировать SVG на диск, я просто хочу иметь возможность извлечь svg из файла jar и получить его как элемент пользовательского интерфейса.

Я чувствую, что это должно быть достаточно легко, но Javadocs батика не говорят мне, что мне нужно знать.

(Почему батик? Ну, мы уже используем его, поэтому нам не нужно запускать другую библиотеку, кроме юридической.)

Ответы [ 5 ]

19 голосов
/ 23 марта 2010

Это действительно довольно просто, просто не очень интуитивно понятно.

Вам необходимо расширить 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 в нулевую цель.Затем вызовите геттер вашего транскодера, чтобы получить изображение.

Вызов выглядит примерно так:

    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 голосов
/ 17 июня 2012

Если вы больше не хотите включать зависимость от Batik в свое приложение, вы можете преобразовать файл SVG непосредственно в Java2D с помощью транскодера Flamingo SVG:

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

Он генерирует классы значков, примерно эквивалентные по размеру сжатому файлу SVG. Сгенерированный код не имеет внешней зависимости.

3 голосов
/ 09 июля 2011

Я только что последовал за подходом Девона к батику-1.7

Однако, чтобы заставить его работать, мне пришлось сделать следующие дополнения к объекту подсказок:

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.

0 голосов
/ 21 апреля 2016

Я пытался использовать предложения Девона и Джона, которые мне почти помогли Мне пришлось сделать некоторые настройки следующим образом, не стесняйтесь использовать:

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 голосов
/ 03 августа 2013

Чтобы избежать передачи параметров dom: transcoder.setTranscodingHints((Map<?, ?>) hints);

...