A high-performance SVG 1.1 to PNG, JPEG, TIFF, PDF, and PS/EPS converter powered by Java2D. API inspired by CairoSVG.
- Zero native dependencies — pure Java, runs anywhere the JVM runs
- No heavyweight frameworks — no Batik, no Cairo, no WebKit; just Java2D
- Secure by default — XXE protection enabled,
<script>elements ignored, external resource access disabled unless explicitly opted in - Fast — 3-30× faster than EchoSVG (Batik), competitive with JSVG, 1-2× faster than CairoSVG's native C backend
- Drop-in API — static one-liners, fluent builder, or CLI — your choice
- 🎨 SVG 1.1 rendering using Java2D — no native dependencies (with selective SVG 2 alignment)
- 📄 Multiple output formats: PNG, JPEG, TIFF, PDF (via optional Apache PDFBox), PostScript/EPS
- 🔷 Full shape support: rect, circle, ellipse, line, polygon, polyline, path
- 🌈 Gradients: linear and radial with stop colors, opacity, and
spreadMethod - ✍️ Text rendering with font control, letter-spacing, text-anchor,
<tspan>, and<textPath> - 🔄 Transforms: translate, rotate, scale, skewX, skewY, matrix
- 🎭 Definitions:
<use>,<symbol>,<defs>, clip-path, viewBox, preserveAspectRatio - 🖌️ Patterns:
<pattern>withpatternTransformandpatternUnits - 🎯 Markers:
<marker>withorient="auto"tangent direction support - 😷 Masks:
<mask>with luminance-to-alpha compositing - 🔍 Filters:
feGaussianBlur,feOffset,feFlood,feBlend,feMerge,feDropShadow,feImage,feTile - 🔤 SVG Fonts:
<font>and<glyph>with system font fallback for undefined characters - 🎨 CSS: stylesheets, inline styles, CSS variables (
var()),currentColor,inherit - 🔀 Conditional processing:
<switch>,systemLanguage,requiredExtensions - ⚡ Fast: 3-29× faster than EchoSVG (Batik fork), on par with JSVG, 1-2.6× faster than CairoSVG's native C backend
- 🛡️ Secure: XML external entity (XXE) protection by default
- 🧰 Flexible API: Static methods, fluent builder, CLI
| Test Case | JairoSVG (Java) | EchoSVG (Java) | JSVG (Java) | CairoSVG (Python) |
|---|---|---|---|---|
| Simple shapes | 4.3 ms | 20.9 ms | 4.3 ms | 5.7 ms |
| Gradients | 5.8 ms | 169.5 ms | 5.8 ms | 12.7 ms |
| Filters | 9.8 ms | 45.3 ms | 11.2 ms | 6.3 ms |
| Fe blend modes | 13.6 ms | 37.8 ms | 28.5 ms | 24.2 ms |
| Embedded image | 5.8 ms | 22.3 ms | 7.7 ms | 10.8 ms |
| Localized masks | 19.4 ms | 66.3 ms | 19.7 ms | 25.9 ms |
JairoSVG is 3–29× faster than EchoSVG, on par with JSVG for simple SVGs, and significantly faster on filters, blends, masks, and images.
Run the benchmark yourself: jbang comparison/benchmark/benchmark.java.
See comparison/README.md for full benchmark results, PNG file size comparisons, and feature matrices across JairoSVG, EchoSVG, CairoSVG, and JSVG.
See comparison/COMPARISON.md for side-by-side rendered PNG comparisons, benchmark times, and file sizes across 42 SVG test cases.
Tip: Check Maven Central for the latest released version.
Download the standalone CLI jar from the GitHub Releases page:
# Download the CLI jar (requires Java 25+)
java -jar jairosvg-{version}-cli.jar input.svg -o output.png
# Convert multiple files at once
java -jar jairosvg-{version}-cli.jar *.svg -o output-dir/<dependency>
<groupId>io.brunoborges</groupId>
<artifactId>jairosvg</artifactId>
<version>1.0.10</version>
</dependency>Note: PDF output requires Apache PDFBox on the classpath. It is an optional dependency — if you only need PNG, JPEG, TIFF, or PS/EPS output, you do not need to add PDFBox. To enable PDF support, add it explicitly:
<dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> <version>3.0.7</version> </dependency>
implementation 'io.brunoborges:jairosvg:1.0.10'jbang --deps io.brunoborges:jairosvg:1.0.10 MyScript.javaimport io.brunoborges.jairosvg.JairoSVG;
// SVG bytes → PNG bytes
byte[] png = JairoSVG.svg2png(svgBytes);
// SVG file → PDF file
JairoSVG.svg2pdf(Path.of("input.svg"), Path.of("output.pdf"));
// One-liner conversions for all formats
byte[] jpeg = JairoSVG.svg2jpeg(svgBytes);
byte[] tiff = JairoSVG.svg2tiff(svgBytes);
byte[] ps = JairoSVG.svg2ps(svgBytes);
byte[] eps = JairoSVG.svg2eps(svgBytes);
// File-to-file for any format
JairoSVG.svg2jpeg(Path.of("input.svg"), Path.of("output.jpg"));
JairoSVG.svg2tiff(Path.of("input.svg"), Path.of("output.tiff"));
JairoSVG.svg2ps(Path.of("input.svg"), Path.of("output.ps"));
JairoSVG.svg2eps(Path.of("input.svg"), Path.of("output.eps"));
// Builder API with options
byte[] scaled = JairoSVG.builder()
.fromBytes(svgBytes)
.dpi(150)
.scale(2)
.backgroundColor("#ffffff")
.toPng();
// Control image compression/quality
byte[] fastPng = JairoSVG.builder()
.fromFile(Path.of("icon.svg"))
.pngCompressionLevel(1) // 0 (fastest) to 9 (smallest)
.toPng();
byte[] highQualityJpeg = JairoSVG.builder()
.fromFile(Path.of("photo.svg"))
.jpegQuality(0.95f) // 0.0 (smallest) to 1.0 (best)
.toJpeg();
// Get BufferedImage directly
BufferedImage image = JairoSVG.builder()
.fromFile(Path.of("icon.svg"))
.toImage();
// SVG string → PNG
byte[] png = JairoSVG.builder()
.fromString("<svg>...</svg>")
.toPng();
// Stream input
byte[] fromStream = JairoSVG.builder()
.fromStream(inputStream)
.toPng();
// PS/EPS output (returns byte[])
byte[] ps = JairoSVG.builder()
.fromFile(Path.of("diagram.svg"))
.toPs();
byte[] eps = JairoSVG.builder()
.fromFile(Path.of("diagram.svg"))
.toEps();
// TIFF output
JairoSVG.builder()
.fromFile(Path.of("drawing.svg"))
.toTiff(new FileOutputStream("output.tiff"));
// Negate colors + output dimensions
byte[] inverted = JairoSVG.builder()
.fromBytes(svgBytes)
.negateColors(true)
.outputWidth(800)
.outputHeight(600)
.toPng();
// Unsafe mode (allows external file access)
byte[] result = JairoSVG.builder()
.fromUrl("https://example.com/chart.svg")
.unsafe(true)
.toPng();
// Customize Java2D rendering hints
import java.awt.RenderingHints;
byte[] quality = JairoSVG.builder()
.fromBytes(svgBytes)
.renderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY)
.toPng();Install with JBang
jbang app install io.brunoborges:jairosvg:LATEST
# SVG → PNG
jairosvg input.svg -o output.png
# SVG → PDF with 2x scale
jairosvg input.svg -f pdf -s 2 -o output.pdf
# Convert multiple files to a directory
jairosvg *.svg -o output-dir/Or download the CLI jar from GitHub Releases:
# SVG → PNG
java -jar jairosvg-{version}-cli.jar input.svg -o output.png
# SVG → PDF with 2x scale
java -jar jairosvg-{version}-cli.jar input.svg -f pdf -s 2 -o output.pdf
# Convert multiple files to a directory
java -jar jairosvg-{version}-cli.jar *.svg -o output-dir/Build from source:
mvn package
java -jar target/jairosvg-{version}-cli.jar input.svg -o output.png| Option | Description |
|---|---|
-o, --output FILE|DIR |
Output filename or directory (default: stdout) |
-f, --format FORMAT |
Output format: png, jpeg, tiff, pdf, ps, eps |
-d, --dpi DPI |
Resolution (default: 96) |
-s, --scale FACTOR |
Scale factor (default: 1) |
-b, --background COLOR |
Background color |
-W, --width PIXELS |
Parent container width |
-H, --height PIXELS |
Parent container height |
--output-width PIXELS |
Desired output width |
--output-height PIXELS |
Desired output height |
-n, --negate-colors |
Negate vector colors |
-i, --invert-images |
Invert raster image colors |
-u, --unsafe |
Allow external file access |
When multiple input files are given, -o specifies an output directory. Output filenames are derived from input names with the appropriate extension.
- ✅ Basic shapes:
rect,circle,ellipse,line,polygon,polyline - ✅ Path commands: M, L, C, S, Q, T, A, H, V, Z (absolute and relative)
- ✅
<use>,<symbol>,<defs>,<g> - ✅
<svg>with nesting and viewBox - ✅
<image>— embedded raster (data URI and external) and nested SVG - ✅
<text>,<tspan>,<textPath>,<a> - ✅
<marker>withorient="auto"tangent direction - ✅
<clipPath> - ✅
<mask>with luminance-to-alpha compositing - ✅
<pattern>withpatternTransformandpatternUnits - ✅
<linearGradient>,<radialGradient>withspreadMethodand href chaining - ✅
<font>,<font-face>,<glyph>,<missing-glyph>(SVG fonts) - ✅
<switch>with conditional processing (systemLanguage,requiredExtensions) - ✅
<cursor>,<foreignObject>(parsed but not rendered — see LIMITATIONS.md)
- ✅
<filter>withfilterUnitsand sub-region optimization - ✅
feGaussianBlur,feOffset,feFlood,feBlend(normal, multiply, screen, darken, lighten) - ✅
feMerge,feComposite(over, in, out, atop, xor, arithmetic),feDropShadow - ✅
feImage(data URI + inline references),feTile - ✅
feColorMatrix(matrix, saturate, hueRotate, luminanceToAlpha) - ✅
feComponentTransfer(identity, linear, gamma, table, discrete) - ✅
feMorphology(erode, dilate),feConvolveMatrix - ✅
feTurbulence(turbulence, fractalNoise),feDisplacementMap - ✅
feDiffuseLighting,feSpecularLighting(distant, point, spot lights)
- ✅ CSS stylesheets (embedded
<style>) and inlinestyleattributes - ✅ CSS
@importrules (URL resolution with circular import detection) - ✅ CSS selectors: class, id, element, descendant,
:first-child,:last-child,:nth-child(),:not() - ✅ CSS custom properties / variables (
var(--name, fallback)) - ✅
currentColor,inherit - ✅ Opacity: element, fill, stroke, group
- ✅
display,visibility
- ✅ Transforms: translate, rotate, scale, skewX, skewY, matrix
- ✅ viewBox and preserveAspectRatio (all 9 align values + meet/slice)
- ✅ Stroke properties: dasharray, dashoffset, linecap, linejoin, miterlimit, width
- ✅ Named colors (170+), hex,
rgb(),rgba(),hsl(),hsla() - ✅ Units: px, pt, em, ex, %, cm, mm, in, pc
JairoSVG renders SVG through the standard Java2D (Graphics2D / BufferedImage) API. The architecture is intentionally compact:
| Java Class | Role |
|---|---|
JairoSVG |
Public API + fluent Builder |
Surface |
Java2D rendering engine + state mgmt |
Node |
SVG DOM tree with CSS cascade |
PathDrawer |
SVG path commands → GeneralPath |
ShapeDrawer |
Basic shape elements |
TextDrawer |
Text, tspan, textPath rendering |
Defs |
Definition elements + clip paths |
GradientPainter |
Linear/radial gradient rendering |
PatternPainter |
Pattern → TexturePaint |
MaskPainter |
Mask luminance-to-alpha compositing |
MarkerDrawer |
Marker placement and orientation |
FilterRenderer |
Filter pipeline (blur, blend, merge...) |
GaussianBlur |
Optimized box-blur Gaussian |
BlendCompositor |
feBlend pixel blending modes |
ImageHandler |
Embedded image handling |
SvgDrawer |
Nested <svg> viewport handling |
Colors |
Color parsing (170+ named) |
CssProcessor |
CSS parsing and selector matching |
SvgFont |
SVG font glyph caching |
Helpers |
Units, transforms, aspect ratio |
Main |
CLI entry point |
Key technologies:
java.awt.Graphics2D— 2D rendering contextjava.awt.image.BufferedImage— raster image bufferjava.awt.geom.AffineTransform— coordinate transforms- Apache PDFBox 3.0 — PDF output (optional dependency)
# Clone and build
git clone https://github.com/brunoborges/jairosvg.git
cd jairosvg
./mvnw clean verify
# Run tests
./mvnw test
# Generate documentation site
./mvnw siteSee LIMITATIONS.md for known and intentional limitations (including unsupported embedded content such as <foreignObject>).
See CONTRIBUTING.md for guidelines on building, testing, and submitting pull requests.
JairoSVG is licensed under the MIT License.