Skip to content
carlosame edited this page Sep 5, 2023 · 5 revisions

EchoSVG supports converting a few formats from and to SVG, for example:


Prerequisites

First, you have to declare a dependency on the echosvg-transcoder module in your build, for example in Gradle you would put the following in your build.gradle file (see Gradle Notes for more information):

Then, in your build.gradle file you can list the dependencies, for example:

dependencies {
    implementation "io.sf.carte:echosvg-transcoder:${echosvgVersion}"
}

or the equivalent if you use Maven (please read Maven Notes first).

If your project is modular, do not forget

requires io.sf.carte.echosvg.transcoder

API

The base interface for transcoding is Transcoder, and there you will find a single method used to transcode, which takes input and output objects:

void transcode(TranscoderInput input, TranscoderOutput output) throws TranscoderException;

Different transcoders allow you to achieve different things, and in order to configure the transcoding you can set several transcoding hints, which are documented in the API javadocs. Not all of the hints apply to all the transcoders, but common ones that you may use are the following:

KEY_DOCUMENT_ELEMENT, KEY_DOCUMENT_ELEMENT_NAMESPACE_URI

You only need to set those hints if you process SVG inside an HTML document, in which case you should do the following:

transcoder.addTranscodingHint(XMLAbstractTranscoder.KEY_DOCUMENT_ELEMENT_NAMESPACE_URI,
     "http://www.w3.org/1999/xhtml");
transcoder.addTranscodingHint(XMLAbstractTranscoder.KEY_DOCUMENT_ELEMENT, "html");

KEY_WIDTH, KEY_HEIGHT

Expressed in CSS pixels, let you scale the image.

transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_WIDTH, 600f);
transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_HEIGHT, 600f);

KEY_MEDIA

Set a valid CSS medium.

transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_MEDIA, "print");

KEY_EXECUTE_ONLOAD

Execute the script's onload event (Javascript is supported via Rhino but should not be used on untrusted scripts, please read SECURITY.md).

transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_EXECUTE_ONLOAD, Boolean.TRUE);

KEY_SVG_SELECTOR

If the SVG image is embedded inside an HTML document which contains several embedded SVGs, you can set a selector that points to the desired one.

transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_SVG_SELECTOR, ".svgclass");

KEY_DEFAULT_FONT_FAMILY

As the name implies, allows setting the default font family.

transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_DEFAULT_FONT_FAMILY, "Helvetica");

KEY_USER_STYLESHEET_URI

A URI to a user stylesheet that can be employed to customize the styles.

transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_USER_STYLESHEET_URI, "file:///path/to/user.css");

KEY_BACKGROUND_COLOR

For image transcoders only, allows setting a background color.

transcoder.addTranscodingHint(ImageTranscoder.KEY_BACKGROUND_COLOR, Color.cyan);

KEY_QUALITY

For the JPEG transcoder only, sets the desired quality (0 to 1).

transcoder.addTranscodingHint(JPEGTranscoder.KEY_QUALITY, 0.86f);

Examples

Transcode an SVG file into PNG

// Instantiate and configure the transcoder
PNGTranscoder transcoder = new PNGTranscoder();
transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_DEFAULT_FONT_FAMILY, "Open Sans");

// It is recommended to set the URI
String uri = originFile.toURI().toString();
TranscoderInput input = new TranscoderInput(uri);

// Read the file and transcode
try (FileReader reader = new FileReader(originFile, StandardCharsets.UTF_8);
        FileOutputStream ostream = new FileOutputStream(destinationFile)) {
    input.setReader(reader);
    TranscoderOutput output = new TranscoderOutput(ostream);
    transcoder.transcode(input, output);
}

Transcode from the JDK DOM

Sometimes we want to transcode a document that we got from a different DOM implementation. In this example we first load the document into the JDK's DOM, then transcode it.

// Instantiate and configure the transcoder
PNGTranscoder transcoder = new PNGTranscoder();
transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_DEFAULT_FONT_FAMILY, "Open Sans");

// The DocumentBuilder
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
dbFactory.setNamespaceAware(true);
DocumentBuilder builder = dbFactory.newDocumentBuilder();
Document document;

// Parse into DOM
try (FileReader reader = new FileReader(originFile, StandardCharsets.UTF_8)) {
    document = builder.parse(reader);
}

// It is recommended to set the URI
document.setDocumentURI(originFile.toURI().toString());

// The document is the input
TranscoderInput input = new TranscoderInput(document);

try (FileOutputStream ostream = new FileOutputStream(destinationFile)) {
    TranscoderOutput output = new TranscoderOutput(ostream);
    transcoder.transcode(input, output);
}

Transcode SVG located inside an HTML file

Now we have an HTML document which contains a single SVG file that we want to transcode (set KEY_SVG_SELECTOR if the document contains multiple embedded SVG images). To parse the HTML we employ the validator.nu parser, which is one of the parsers used by Mozilla Firefox.

First we make sure to put the parser in the class/module path. In Gradle:

implementation group: 'nu.validator', name: 'htmlparser', version: '1.4.16'

Then the Java code would be like the following

// Instantiate and configure the transcoder
PNGTranscoder transcoder = new PNGTranscoder();
transcoder.addTranscodingHint(XMLAbstractTranscoder.KEY_DOCUMENT_ELEMENT_NAMESPACE_URI,
     "http://www.w3.org/1999/xhtml");
transcoder.addTranscodingHint(XMLAbstractTranscoder.KEY_DOCUMENT_ELEMENT, "html");
transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_DEFAULT_FONT_FAMILY, "Open Sans");

// It is recommended to set the URI
String uri = originFile.toURI().toString();
TranscoderInput input = new TranscoderInput(uri);

// Instantiate and configure the parser
HtmlParser parser = new HtmlParser(XmlViolationPolicy.ALTER_INFOSET);
parser.setCommentPolicy(XmlViolationPolicy.ALLOW);
parser.setXmlnsPolicy(XmlViolationPolicy.ALLOW);

input.setXMLReader(parser);

// Read the file and transcode
try (FileReader reader = new FileReader(originFile, StandardCharsets.UTF_8);
        FileOutputStream ostream = new FileOutputStream(destinationFile)) {
    input.setReader(reader);
    TranscoderOutput output = new TranscoderOutput(ostream);
    transcoder.transcode(input, output);
}

Modern CSS with CSSTranscodingHelper

If you need support for more modern CSS than the basic Transcoder infrastructure provides, give the CSSTranscodingHelper a try. It is basically a wrapper over the transcoder, with support for recent CSS and (to some extent) foreign elements.