I'm using the Apache Batik Java library to convert .svg
vector image file to a .png
file. The problem is that the font colors of the generated .png
image are all going black. Here is the code that I'm using to do the conversion:
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;
}
}
Using the AndroidSVG
library on the same .svg
file generates the correct .png
image with the correct colors.
Another note; Using the default font of inkscape
(the program I use to create vector graphics) solves this problem. Using any other font face causes Batik to change its colors to black.
Inkscape adds a custom CSS property, -inkscape-font-specification
, to the style
attribute associated with custom font text. Here's an excerpt:
style="...;-inkscape-font-specification:'Aharoni, Bold';..."
A known Batik bug prevents rendering CSS properties that start with a hyphen (-
).
A simple fix is to edit the file and then remove the "-inkscape-font-specification" attributes.
Alternatively, you could use Batik's API to create a new CSS style parser that removes the offending CSS style class. For example:
/**
* <a href="https://issues.apache.org/jira/browse/BATIK-1112">Bug fix</a>
*/
public static final class InkscapeCssParser extends Parser {
public void parseStyleDeclaration( final String source )
throws CSSException, IOException {
super.parseStyleDeclaration(
source.replaceAll( "-inkscape-font-specification:[^;\"]*;", "" )
);
}
}
static {
XMLResourceDescriptor.setCSSParserClassName(
InkscapeCssParser.class.getName()
);
}