Skip to content
carlosame edited this page Jul 24, 2024 · 6 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:

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");

Expressed in CSS pixels, let you scale the image.

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

Set a valid CSS medium.

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

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);

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");

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

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

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");

For image transcoders only, allows setting a background color.

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

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

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

Sets the compression level used in the PNG encoding (the default native encoder uses 9 by default, which is excessive for some use cases).

transcoder.addTranscodingHint(PNGTranscoder.KEY_COMPRESSION_LEVEL, 4);

Embed textual information (like copyright, author, description, etc) in rendered PNG images.

String[] text = { "Copyright", "Copyright © 2024 ACME Inc.",
    "Description", "Bar chart",
    "Software", "EchoSVG" };

transcoder.addTranscodingHint(PNGTranscoder.KEY_KEYWORD_TEXT, text);

Embed compressed textual information (like copyright, author, description, etc) in rendered PNG images.

String[] text = { "Copyright", "Copyright © 2024 ACME Inc.",
    "Description", "Bar chart",
    "Software", "EchoSVG" };

transcoder.addTranscodingHint(PNGTranscoder.KEY_COMPRESSED_TEXT, text);

This one is like KEY_KEYWORD_TEXT but compressed.

Embed internationalized textual information in rendered PNG images.

String[] iText = { "Description", "en", "Description", "My image.",
    "Description", "es", "Descripción", "Mi imagen." };

transcoder.addTranscodingHint(PNGTranscoder.KEY_INTERNATIONAL_TEXT, iText);

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.