从 SVG 文件创建非缓冲 java.awt.Image

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

我有一些现有的代码,看起来很像 Swing & Batik:从 SVG 文件创建 ImageIcon?

上的解决方案

但是我的图像的目标是 PDF,令我烦恼的是,当您放大 PDF 时,您会看到像素。如果源数据和目标数据都是矢量图形,应该可以直接渲染。

我们使用的库(iText)采用 java.awt.Image,但我似乎不知道如何获取呈现 SVG 的 java.awt.Image。 Batik有办法做到这一点吗?

java svg batik
2个回答
1
投票

嗯,这就是我最终所做的。

java.awt.Image
确实是一条死胡同。有一个解决方案,将
PdfTemplate
包裹在
ImgTemplate
中,这样它就可以用作 iText
Image

(我必须将它放在知道其大小的东西中,因为它是在表格中使用的,否则布局会变得完全疯狂。

Image
似乎知道这一点。)

public class SvgHelper {
    private final SAXSVGDocumentFactory factory;
    private final GVTBuilder builder;
    private final BridgeContext bridgeContext;

    public SvgHelper() {
        factory = new SAXSVGDocumentFactory(
            XMLResourceDescriptor.getXMLParserClassName());
        UserAgent userAgent = new UserAgentAdapter();
        DocumentLoader loader = new DocumentLoader(userAgent);
        bridgeContext = new BridgeContext(userAgent, loader);
        bridgeContext.setDynamicState(BridgeContext.STATIC);
        builder = new GVTBuilder();
    }

    public Image createSvgImage(PdfContentByte contentByte, URL resource,
                                float maxPointWidth, float maxPointHeight) {
        Image image = drawUnscaledSvg(contentByte, resource);
        image.scaleToFit(maxPointWidth, maxPointHeight);
        return image;
    }

    public Image drawUnscaledSvg(PdfContentByte contentByte, URL resource) {
        GraphicsNode imageGraphics;
        try {
            SVGDocument imageDocument = factory.createSVGDocument(resource.toString());
            imageGraphics = builder.build(bridgeContext, imageDocument);
        } catch (IOException e) {
            throw new RuntimeException("Couldn't load SVG resource", e);
        }

        float width = (float) imageGraphics.getBounds().getWidth();
        float height = (float) imageGraphics.getBounds().getHeight();

        PdfTemplate template = contentByte.createTemplate(width, height);
        Graphics2D graphics = template.createGraphics(width, height);
        try {
            // SVGs can have their corner at coordinates other than (0,0).
            Rectangle2D bounds = imageGraphics.getBounds();

            //TODO: Is this in the right coordinate space even?
            graphics.translate(-bounds.getX(), -bounds.getY());

            imageGraphics.paint(graphics);

            return new ImgTemplate(template);
        } catch (BadElementException e) {
            throw new RuntimeException("Couldn't generate PDF from SVG", e);
        } finally {
            graphics.dispose();
        }
    }
}

0
投票

我只是想使用 SVG 图像设置停靠栏图标,所以我需要一个 ImageIcon。经过一周的尝试,我想出了这个解决方案,可以从 Java 支持的任何格式中获取 ImageIcon。如有必要,它会将 SVG 转换为 PNG。 strRes 是资源字符串。

protected static ImageIcon loadIcon(String strRes) {
    if (strRes == null || strRes.isEmpty()) {
      return null;
    }
    // For new ImageIcon(resource, strRes), strRes must NOT begin with "/":
    //   get Exception from PluginClassLoader says "leading '/' doesn't work; strip"
    if (strRes.startsWith("/")) {
      strRes = strRes.substring(1);
    }
    ImageIcon icon = null;
    if (!strRes.contains(" | ")) {
      URL resource = StudioIcons.class.getClassLoader().getResource(strRes);
      if (resource != null) {
        if (strRes.endsWith(".svg")) {
          // To load an ImageIcon from an SVG is "af kapores" (you need to throw a chicken over your head 3 times)
          // This solution converts the image to a PNG and writes it out, then reads it in.
          try {
            Image image = SVGLoader.load(resource, 1f);
            String filename = new File(resource.getPath()).getName() + ".png";
            ImageIO.write((BufferedImage)image, "png", new File(filename));
            icon = new ImageIcon(new File(filename).toURI().getPath(), "Converted from SVG");
          }
          catch (IOException ex) {
            throw new RuntimeException("Cannot convert SVG to PNG: ", ex);
          }
        } else {
          try {
            icon = new ImageIcon(resource, strRes);
          } catch (Exception ignore) {
          }
        }
      }
    }
    return icon;
}

要设置停靠栏图标,我使用:

  if (Taskbar.isTaskbarSupported() ) {
    final Taskbar taskbar = Taskbar.getTaskbar();
    try {
      //set icon for MacOS (and other systems which support this method)
      taskbar.setIconImage(icon); // Was Java Duke
    } catch (final UnsupportedOperationException e) {
      System.out.println("The OS does not support: 'taskbar.setIconImage()'");
    } catch (final SecurityException e) {
      System.out.println("There was a security exception for: 'taskbar.setIconImage()'");
    }
  }
© www.soinside.com 2019 - 2024. All rights reserved.