java - BridgeException: null:-1 将 SVG 转码为 BufferedImage 并引用不存在的掩码
问题描述
任务:使用 Apache Batik 1.14 ( ) 将 SVG 文件转换为 BufferedImage imageTranscoder.transcode(new TranscoderInput(svgDocument), null)
。
问题:它抛出这个异常:
Caused by: org.apache.batik.bridge.BridgeException: null:-1
Cannot find the referenced element:
"#mask-2"
specified on the element <path> - may be a problem of 'id'
at org.apache.batik.bridge.BridgeContext.getReferencedNode(BridgeContext.java:762)
at org.apache.batik.bridge.BridgeContext.getReferencedElement(BridgeContext.java:804)
at org.apache.batik.bridge.CSSUtilities.convertMask(CSSUtilities.java:771)
at org.apache.batik.bridge.AbstractGraphicsNodeBridge.buildGraphicsNode(AbstractGraphicsNodeBridge.java:144)
at org.apache.batik.bridge.SVGShapeElementBridge.buildGraphicsNode(SVGShapeElementBridge.java:92)
at org.apache.batik.bridge.GVTBuilder.buildGraphicsNode(GVTBuilder.java:224)
at org.apache.batik.bridge.GVTBuilder.buildComposite(GVTBuilder.java:171)
at org.apache.batik.bridge.GVTBuilder.buildGraphicsNode(GVTBuilder.java:219)
at org.apache.batik.bridge.GVTBuilder.buildComposite(GVTBuilder.java:171)
at org.apache.batik.bridge.GVTBuilder.build(GVTBuilder.java:82)
at org.apache.batik.transcoder.SVGAbstractTranscoder.transcode(SVGAbstractTranscoder.java:210)
... 108 more
原因/原因是 SVG 文档不包含任何mask
元素,但包含一些path
引用(不存在的)掩码的元素:<path [...] mask="url(#mask-2)" />
。有关掩码的更多信息,请参见此处https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/mask
我的解决方法是检查 SVG 文档并删除所有无效的掩码引用,如下所示:
查找所有有效的掩码 ID:
Set<String> existingMaskIds = new HashSet<>(); NodeList allMaskNodes = svgDocument.getElementsByTagName("mask"); int numberOfMaskNodes = allMaskNodes.getLength(); for (int i = 0; i < numberOfMaskNodes; i++) { Element maskElement = (Element) allMaskNodes.item(i); if (maskElement.hasAttribute("id")) { existingMaskIds.add(maskElement.getAttribute("id")); } }
删除所有无效的掩码引用:
private static void removeInvalidMaskReferences(Node svgNode, Set<String> existingMaskIds) { short nodeType = svgNode.getNodeType(); if (nodeType == Node.ELEMENT_NODE || nodeType == Node.DOCUMENT_NODE) { if (nodeType == Node.ELEMENT_NODE) { Element svgElement = (Element) svgNode; if (svgElement.hasAttribute("mask")) { String maskValue = svgElement.getAttribute("mask"); if (maskValue != null && maskValue.startsWith("url(")) { maskValue = maskValue.replace("url(", ""); maskValue = maskValue.replace(")", ""); maskValue = maskValue.replace("#", ""); maskValue = maskValue.trim(); if (!existingMaskIds.contains(maskValue)) { // Remove mask reference svgElement.removeAttribute("mask"); } } } } if (svgNode.hasChildNodes()) { NodeList children = svgNode.getChildNodes(); if (children != null) { int numberOfChildren = children.getLength(); for (int i = 0; i < numberOfChildren; i++) { removeInvalidMaskReferences(children.item(i), bekannteMaskenIds); } } } } }
我想我不太可能是唯一一个在这件事上绊倒的人。也许有一些 TranscodingHint(或类似的东西)我可以说“请忽略无效的掩码”?不幸的是,我还没有找到类似的 TranscodingHints。
所以我的问题是:我可以将 SVG 文件转码为 BufferedImage 文件,尽管没有我的解决方法代码和(更宽容的)Apache Batik 的无效掩码引用?
解决方案
推荐阅读
- c++ - socket() 返回极大的整数值
- c# - 如何在 vs-community 中更改我的代码而不重新启动我的应用程序?
- node.js - Swagger 无法解析 YAML:“SyntaxError: Unexpected token :”
- xamarin - 跨平台应用活跃下载分析
- html - 即使向下滚动,如何使html,body覆盖全屏
- python - Cuda 错误:触发了设备端断言 - 仅在一定数量的批次之后
- javascript - 为什么 ReactJS 上的布尔玛日历不起作用?
- javascript - 寻找 Highmaps 的默认 yAxis 选项以便能够从代码中添加它
- c# - 时间:2019-01-01 标签:c#linqsort by field in object based on variable
- flutter - Flutter:使用 Streambuilder 时如何在 Firestore 中获取特定文档