java - Apache Batik 无法在 Swing 应用程序中显示 SVG
问题描述
我下面的代码是从官方指南中提取的。该代码将毫无问题地呈现一些 SVG 文件,但其他会导致异常java.awt.image.ImagingOpException: Unable to transform src image
。我创建了一个“工作图像”和一个“问题图像”作为小例子。
请注意,我无法将 SVG 文件直接添加到 StackOverflow 问题中,它们不是受支持的文件类型,因此这里是一个工作图像和一个问题图像的链接。以下也是原始文件内容。
我发现了多个潜在的重复问题,但没有一个有答案。我可以在我自己的程序中解决这个问题而不修补蜡染吗?是否有其他推荐的方式在 Java 中显示 SVG?AFAIK,蜡染是参考实现。是什么导致一个 SVG 失败而另一个(几乎相同)的工作正常?我怎样才能避免这个问题,而不必扫描/编辑我的用户可能选择加载的每个 SVG 以避免一些边缘情况错误?
public class SVGApplication {
public static void main(String[] args) {
// Create a new JFrame.
JFrame f = new JFrame("Batik");
SVGApplication app = new SVGApplication();
app.frame = f;
f.getContentPane().add(app.createComponents());
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
f.setSize(400, 400);
f.setVisible(true);
}
JFrame frame;
JButton button = new JButton("Load...");
JLabel label = new JLabel();
JSVGCanvas svgCanvas = new JSVGCanvas();
public JComponent createComponents() {
final JPanel panel = new JPanel(new BorderLayout());
JPanel p = new JPanel(new FlowLayout(FlowLayout.LEFT));
p.add(button);
p.add(label);
panel.add("North", p);
panel.add("Center", svgCanvas);
// Set the button action.
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
JFileChooser fc = new JFileChooser(".");
int choice = fc.showOpenDialog(panel);
if (choice == JFileChooser.APPROVE_OPTION) {
File f = fc.getSelectedFile();
try {
svgCanvas.setURI(f.toURL().toString());
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
});
return panel;
}
}
对于所有图像,程序最初会很好地加载图像,但是当您缩放 JFrame 时,它开始在“问题”图像上喷出异常,例如
java.awt.image.ImagingOpException: Unable to transform src image
at java.awt.image.AffineTransformOp.filter(AffineTransformOp.java:358)
at org.apache.batik.ext.awt.image.rendered.AffineRed.genRect(AffineRed.java:193)
at org.apache.batik.ext.awt.image.rendered.AffineRed.copyData(AffineRed.java:109)
at org.apache.batik.ext.awt.image.rendered.PadRed.copyData(PadRed.java:88)
at org.apache.batik.ext.awt.image.rendered.ColorMatrixRed.copyData(ColorMatrixRed.java:116)
at org.apache.batik.ext.awt.image.rendered.PadRed.copyData(PadRed.java:88)
at org.apache.batik.ext.awt.image.rendered.PadRed.copyData(PadRed.java:88)
at org.apache.batik.ext.awt.image.rendered.PadRed.copyData(PadRed.java:88)
at org.apache.batik.ext.awt.image.rendered.CompositeRed.genRect(CompositeRed.java:179)
at org.apache.batik.ext.awt.image.rendered.CompositeRed.copyData(CompositeRed.java:139)
at org.apache.batik.ext.awt.image.rendered.Any2sRGBRed.copyData(Any2sRGBRed.java:166)
at org.apache.batik.ext.awt.image.rendered.FormatRed.copyData(FormatRed.java:116)
at org.apache.batik.ext.awt.image.GraphicsUtil.drawImage(GraphicsUtil.java:347)
at org.apache.batik.ext.awt.image.GraphicsUtil.drawImage(GraphicsUtil.java:455)
at org.apache.batik.ext.awt.image.renderable.PadRable8Bit.paintRable(PadRable8Bit.java:135)
at org.apache.batik.ext.awt.image.GraphicsUtil.drawImage(GraphicsUtil.java:440)
at org.apache.batik.ext.awt.image.renderable.PadRable8Bit.paintRable(PadRable8Bit.java:135)
at org.apache.batik.ext.awt.image.GraphicsUtil.drawImage(GraphicsUtil.java:440)
at org.apache.batik.ext.awt.image.renderable.FilterChainRable8Bit.paintRable(FilterChainRable8Bit.java:251)
at org.apache.batik.ext.awt.image.GraphicsUtil.drawImage(GraphicsUtil.java:440)
at org.apache.batik.gvt.AbstractGraphicsNode.paint(AbstractGraphicsNode.java:549)
at org.apache.batik.gvt.ShapeNode.paint(ShapeNode.java:143)
at org.apache.batik.gvt.CompositeGraphicsNode.primitivePaint(CompositeGraphicsNode.java:165)
at org.apache.batik.gvt.AbstractGraphicsNode.paint(AbstractGraphicsNode.java:509)
at org.apache.batik.gvt.CompositeGraphicsNode.primitivePaint(CompositeGraphicsNode.java:165)
at org.apache.batik.gvt.CanvasGraphicsNode.primitivePaint(CanvasGraphicsNode.java:159)
at org.apache.batik.gvt.AbstractGraphicsNode.paint(AbstractGraphicsNode.java:509)
at org.apache.batik.gvt.CompositeGraphicsNode.primitivePaint(CompositeGraphicsNode.java:165)
at org.apache.batik.gvt.AbstractGraphicsNode.paint(AbstractGraphicsNode.java:509)
at org.apache.batik.gvt.renderer.MacRenderer.repaint(MacRenderer.java:360)
at org.apache.batik.gvt.renderer.MacRenderer.repaint(MacRenderer.java:291)
at org.apache.batik.swing.gvt.GVTTreeRenderer.run(GVTTreeRenderer.java:123)
类似的先前问题:这篇文章建议修补蜡染源,这不是很有吸引力。这篇文章解释了一个确实在 batik 1.7+ 中应用的修复,但是我使用的是 1.11,这不再有效
附加数据:因为 SVG 文件似乎很难托管,所以我选择在此处将“工作”与“问题”文件的原始内容作为文本包含在内。这似乎在“完整的、可验证的”问题之间取得了适当的平衡。
Working Image: <?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="141px" preserveAspectRatio="none" style="width:94px;height:141px;" version="1.1" viewBox="0 0 94 141" width="94px" zoomAndPan="magnify"><defs><filter height="300%" id="fdmfjjhypbn8w" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 5.0,5.0;" x1="40" x2="40" y1="38.4883" y2="100.7988"/><rect fill="#FEFECE" filter="url(#fdmfjjhypbn8w)" height="30.4883" style="stroke: #A80036; stroke-width: 1.5;" width="60" x="8" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="46" x="15" y="23.5352">Actor1</text><rect fill="#FEFECE" filter="url(#fdmfjjhypbn8w)" height="30.4883" style="stroke: #A80036; stroke-width: 1.5;" width="60" x="8" y="99.7988"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="46" x="15" y="120.334">Actor1</text><line style="stroke: #A80036; stroke-width: 1.0;" x1="40" x2="82" y1="69.7988" y2="69.7988"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="82" x2="82" y1="69.7988" y2="82.7988"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="41" x2="82" y1="82.7988" y2="82.7988"/><polygon fill="#A80036" points="51,78.7988,41,82.7988,51,86.7988,47,82.7988" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="24" x="47" y="65.0566">test</text><!--@startuml\nActor1 -> Actor1: test\n@enduml--></g></svg>
Problem Image: <?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="183px" preserveAspectRatio="none" style="width:168px;height:183px;" version="1.1" viewBox="0 0 168 183" width="168px" zoomAndPan="magnify"><defs><filter height="300%" id="fc9m2fo3xvklq" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 5.0,5.0;" x1="40" x2="40" y1="38.4883" y2="143.1094"/><line style="stroke: #A80036; stroke-width: 1.0; stroke-dasharray: 5.0,5.0;" x1="114" x2="114" y1="38.4883" y2="143.1094"/><rect fill="#FEFECE" filter="url(#fc9m2fo3xvklq)" height="30.4883" style="stroke: #A80036; stroke-width: 1.5;" width="60" x="8" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="46" x="15" y="23.5352">Actor1</text><rect fill="#FEFECE" filter="url(#fc9m2fo3xvklq)" height="30.4883" style="stroke: #A80036; stroke-width: 1.5;" width="60" x="8" y="142.1094"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="46" x="15" y="162.6445">Actor1</text><rect fill="#FEFECE" filter="url(#fc9m2fo3xvklq)" height="30.4883" style="stroke: #A80036; stroke-width: 1.5;" width="60" x="82" y="3"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="46" x="89" y="23.5352">Actor2</text><rect fill="#FEFECE" filter="url(#fc9m2fo3xvklq)" height="30.4883" style="stroke: #A80036; stroke-width: 1.5;" width="60" x="82" y="142.1094"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="46" x="89" y="162.6445">Actor2</text><line style="stroke: #A80036; stroke-width: 1.0;" x1="40" x2="82" y1="69.7988" y2="69.7988"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="82" x2="82" y1="69.7988" y2="82.7988"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="41" x2="82" y1="82.7988" y2="82.7988"/><polygon fill="#A80036" points="51,78.7988,41,82.7988,51,86.7988,47,82.7988" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="24" x="47" y="65.0566">test</text><line style="stroke: #A80036; stroke-width: 1.0;" x1="114" x2="156" y1="112.1094" y2="112.1094"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="156" x2="156" y1="112.1094" y2="125.1094"/><line style="stroke: #A80036; stroke-width: 1.0;" x1="115" x2="156" y1="125.1094" y2="125.1094"/><polygon fill="#A80036" points="125,121.1094,115,125.1094,125,129.1094,121,125.1094" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="24" x="121" y="107.3672">test</text><!--\n@startuml\nActor1 -> Actor1: test\nActor2 -> Actor2: test\n@enduml\n--></g></svg>
解决方案
推荐阅读
- python - 烧瓶应用程序中未显示分段图像
- java - 无效与单声道
在 Spring webflux 中 - javascript - 循环遍历对象数组并将它们显示在反应组件中
- android - Android Dagger-Hilt 忽略 @Provides 方法
- c - 使用 janet_wrap_array 的正确方法
- javascript - 反应中的 setState 似乎它删除了所有状态内容
- javascript - 添加媒体查询以根据屏幕大小调整日历小部件 css
- c# - 如何使用 VS 代码在控制台应用程序上正确运行 C# 代码?
- sql - Sparklyr:sql 临时错误:参数不可解释为逻辑
- sql - 如何合并 OUTER JOIN 和 UNION 结果?