我使用Apache Batik Java库将.svg
矢量图像文件转换为.png
文件。问题是生成的.png
图像的字体颜色都变黑了。以下是我用来进行转换的代码:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.image.PNGTranscoder;
public class SVGHelperDesktop extends SVGHelper {
@Override
public byte[] convertSvgToPng(String svgXml, float png_width)
throws SVGConversionException {
byte[] resultPngBytes = null;
try {
ByteArrayInputStream inputSvgBytes = new
ByteArrayInputStream(svgXml.getBytes());
TranscoderInput input_svg_image = new
TranscoderInput(inputSvgBytes);
ByteArrayOutputStream outputPngBytes = new ByteArrayOutputStream();
TranscoderOutput output_png_image = new TranscoderOutput(outputPngBytes);
PNGTranscoder svgToPngConverter = new PNGTranscoder();
svgToPngConverter.addTranscodingHint(PNGTranscoder.KEY_WIDTH, png_width);
svgToPngConverter.transcode(input_svg_image, output_png_image);
resultPngBytes = outputPngBytes.toByteArray();
outputPngBytes.flush();
outputPngBytes.close();
} catch (Exception e) {
throw new SVGConversionException("Error converting SVG to PNG", e);
}
return resultPngBytes;
}
}
使用同一.svg
文件上的AndroidSVG
library生成具有正确颜色的正确.png
图片。
另一个说明;使用默认字体inkscape
(我用来创建矢量图形的程序)解决了这个问题。使用任何其他字体使Batik将其颜色更改为黑色。
答案 0 :(得分:1)
确定。解决了问题所在。
当您使用自定义字体时,Inkscape会在-inkscape-font-specification
字母的style
属性中添加自定义CSS属性<path>
。以下是您文件的摘录:
style="... font-family:Aharoni;-inkscape-font-specification:'Aharoni, Bold';font-variant-ligatures:normal; ..."
然而,似乎Batik有一个错误,它不喜欢以短划线/连字符(“ - ”)开头的CSS属性。 This is a known bug it seems
如果您需要使用一组固定的SVG,那么最简单的修复就是手动编辑SVG文件,例如,搜索并将“-inkscape-font-specification”替换为“inkscape-”字体规格”。
如果你想要一个更通用的解决方法,那么上面的Batik bug链接有一个建议的解决方法来覆盖Batik的样式属性解析器。
答案 1 :(得分:0)
接受的答案非常有帮助地指向Batik bug 1112,指示未正确解析“ -inkscape-font-specification”。该错误报告提供了一种变通方法,该方法可以通过重新实现Batik中的CSS解析器的一部分来实现。要对此进行扩展并在此处使其可用,这是我的变通方法的简化版本。
首先需要一个CSS解析器类来覆盖Batik中的类:
import org.apache.batik.css.parser.ExtendedParser;
import org.apache.batik.css.parser.Parser;
import org.w3c.css.sac.CSSException;
import java.io.IOException;
public class InkscapeCssParser extends Parser {
public void parseStyleDeclaration(String source)
throws CSSException, IOException {
source = source.replaceAll(";-inkscape", ";inkscape");
super.parseStyleDeclaration(source);
}
}
请注意,source
参数是特定SVG元素的CSS样式,而不是完整的SVG源。具有parseStyleDeclaration
属性的每个元素都会调用style
。
Batik错误中提供的解决方法重新实现了一个不错的parseStyleDeclaration
块,但我只是简单地执行了一个天真的字符串替换,以消除“;”之后令人讨厌的“-”。因为这是问题的核心。
要使用此功能,请在加载文档之前设置CSS解析器类名称:
JSVGCanvas mSvgCanvas;
XMLResourceDescriptor.setCSSParserClassName(InkscapeCssParser.class.getName());
mSvgCanvas.setURI(svgUrl.toString());