Apache Batik 配置参数详解
梳理 Apache Batik 1.19 全部配置入口:rasterizer 命令行参数与真实默认值、Transcoder 提示键、解析器系统属性、脚本安全沙箱与策略资源、Squiggle 偏好,逐项实测并给出光栅化服务推荐参数集。
Apache Batik 配置参数详解
目标:把 Apache Batik 1.19 的全部配置入口一次讲清——命令行参数与真实默认值、Transcoder 提示键、解析器系统属性、脚本安全沙箱与策略资源、Squiggle 偏好存储,每项配置都配实测命令与回显,并在文末给出光栅化服务的推荐参数集,已在 Ubuntu 22.04(OpenJDK 17.0.20.1)与 CentOS 8.4(OpenJDK 8/17)双环境实测通过。
一、环境信息
本篇所有命令与回显均在以下环境中实测采集:
- 操作系统:Ubuntu 22.04.5 LTS(主环境)、CentOS 8.4.2105(对照环境),x86_64
- JDK:OpenJDK 17.0.20.1(Ubuntu)/ OpenJDK 1.8.0_312 与 17.0.1(CentOS)
- 组件版本:Apache Batik 1.19(官方 batik-bin 发行包 + Maven org.apache.xmlgraphics:batik-transcoder 1.19)
- 实验目录:
/opt/batik(发行包根)、/opt/lab(测试文件) - 执行用户:root
二、前置条件
本篇示例直接复用发行包与一个最小 Maven/手动工程;若从零开始,先完成发行包解压:
java -jar /opt/batik/batik-rasterizer-1.19.jar 2>&1 | head -3
输出节选(实测首部,JDK 17 下含 4 行 WARNING,此处节选选项表开头):
SVG Rasterizer options are:
-d <dir|file>
output directory. If there is a single input file, this can be a file.
工具可用即说明环境就绪。测试 SVG(/opt/lab/hello.svg,400x200):
cat > /opt/lab/hello.svg << "SVGEOF"
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="200" viewBox="0 0 400 200">
<rect x="0" y="0" width="400" height="200" fill="#1e88e5"/>
<circle cx="80" cy="100" r="50" fill="#ffca28"/>
<text x="150" y="110" font-family="DejaVu Sans" font-size="32" fill="#ffffff">Hello Batik</text>
</svg>
SVGEOF
回显(实测,写入成功无输出):
三、配置体系总览
先厘清「Batik 从哪里读配置」。实测对发行包全部 jar 做字节检索:
cd /opt/batik/lib && for j in *.jar; do unzip -p $j 2>/dev/null | grep -qa "batik.properties" && echo "FOUND $j"; done
回显(实测,全部 jar 无命中):
结论:Batik 1.19 不存在名为 batik.properties 的用户配置文件(旧资料偶有提及,请勿照找)。1.19 的真实配置入口共四类,本篇逐类详解:
| 入口 | 载体 | 生效范围 |
|---|---|---|
| 命令行参数 | rasterizer/svgpp/ttf2svg 的选项 | 单次调用 |
| Transcoder 提示键 | addTranscodingHint(KEY_*, value) | 单次 API 调用 |
| 系统属性 | org.xml.sax.driver、org.w3c.css.sac.driver 等,java -D 注入 | JVM 进程级 |
| 安全策略资源 | jar 内 rasterizer.policy/svgbrowser.policy 策略文件 | 脚本沙箱 |
另外 Squiggle 浏览器的界面偏好通过 JVM 标准的 java.util.prefs 持久化(见第八章)。
四、命令行参数详解(rasterizer)
rasterizer 是最常用的转换入口,先取完整选项表作为参数清单基准(实测无参运行输出,逐行照抄):
java -jar /opt/batik/batik-rasterizer-1.19.jar
回显(实测全文,已剔除 JDK 17 的 4 行 WARNING):
SVG Rasterizer options are:
-d <dir|file>
output directory. If there is a single input file, this can be a file.
-m <mimeType>
output mime type.
-w <width>
output width. This is a floating point value.
-h <height>
output height. This is a floating point value.
-maxw <width>
Maximum output width. This is a floating point value.
-maxh <height>
Maximum output height. This is a floating point value.
-a <area>
output area. The format for <area> is x,y,w,h, where x, y, w and h
are floating point values.
-bg <color>
ouput color. The format for <color> is a.r.g.b, where a, r, g and b
are integer values.
-cssMedia <media>
CSS media type for which the source SVG files should be
converted.
-cssAlternate <alternate>
CSS alternate stylesheet to use when converting the source
SVG files.
-cssUser <userStylesheet>
CSS user stylesheet URI to apply to converted SVG documents
in addition to any other referened or embeded stylesheets.
-font-family <defaultFontFamily>
Value used as a default when no font-family value
is specified.
-lang <userLanguage>
User language to use when converting SVG documents.
-q <quality>
Quality for the output image. This is only relevant for the
image/jpeg mime type.
-indexed (1|2|4|8)
Reduces the image to given number of bits per pixel using an
adaptive pallete, resulting in an Indexed image. This is
currently only supported for PNG conversion.
-dpi <resolution>
Resolution for the ouptut image.
-validate
Controls whether the source SVG files should be validated.
-onload
Controls if the source SVG files must be rasterize after
dispatching the 'onload' event.
-snapshotTime <time>
Specifies the document time that should be seeked to before
rasterizing the document. Specifying this option implies -onload.
-scriptSecurityOff removes any security check on the scripts running
as a result of dispatching the onload event.
-anyScriptOrigin controls whether scripts can be loaded from
any location. By default, scripts can only be loaded from
the same location as the document referencing them.
-scripts <listOfAllowedScripts> List of script types (i.e.,
values for the type attribute in the <script> tag) which
should be loaded.
⚠️ 注意:rasterizer 没有
-help/--help选项——实测java -jar batik-rasterizer-1.19.jar -help会把-help当成待转换文件而报错:Error: no output directory specified and source is not a file (source causing failure is "file:-help"。看帮助的正确方式就是无参运行。
4.1 输出位置与格式:-d、-m
-d 指定输出目录(单输入文件时也可以是文件名),-m 指定 MIME 类型决定输出格式。不传 -d 时输出写在源文件旁边:
java -jar /opt/batik/batik-rasterizer-1.19.jar /opt/lab/hello.svg
输出节选(实测):
Converting hello.svg to /opt/lab/hello.png ... ... success
java -jar /opt/batik/batik-rasterizer-1.19.jar -m image/jpeg -d /opt/lab/out /opt/lab/hello.svg
输出节选(实测):
Converting hello.svg to /opt/lab/out/hello.jpg ... ... success
两点实测结论:默认格式为 PNG、输出文件名与源同名仅换扩展名;-m image/tiff 时扩展名是 .tif(不是 .tiff,实测产物文件名 hello.tif)。
4.2 尺寸参数:-w、-h、-maxw、-maxh、-dpi、-a
用 PNG 头部(IHDR 块)核对每个参数的实际输出尺寸,od 读取第 16~23 字节即宽高(大端 4 字节整数):
java -jar /opt/batik/batik-rasterizer-1.19.jar -w 800 -h 400 -d /opt/lab/out-wh /opt/lab/hello.svg
输出节选(实测):
Converting hello.svg to /opt/lab/out-wh/hello.png ... ... success
od -An -tu1 -j16 -N8 /opt/lab/out-wh/hello.png
回显(实测):
0 0 3 32 0 0 1 144
前三字节拼出宽 0x0320=800、后四字节高 0x0190=400,-w/-h 精确生效。其余参数实测结果汇总:
| 参数 | 实测输入 | 实测输出尺寸 | 结论 |
|---|---|---|---|
-maxw 200 | 400x200 源 | 200x100 | 等比缩到上限,保持纵横比 |
-a 100,50,200,100 单独 | 400x200 源 | 400x200 | AOI 区域被缩放铺满画布,尺寸不变 |
-a 100,50,200,100 -w 200 -h 100 | 400x200 源 | 200x100 | 与 -w/-h 组合才得到原比例裁剪 |
-dpi 150 | 无单位 px 的 SVG | 400x200(不变) | dpi 只影响带物理单位的文档 |
-dpi 150 | width="10cm" height="5cm" 的 SVG | 591x295 | 10cm 在 150dpi 下为 591px(默认 96dpi 时 378px) |
物理单位对照实测(cm 版 SVG 默认渲染):
od -An -tu1 -j16 -N8 /opt/lab/out/cm96/hello-cm.png && od -An -tu1 -j16 -N8 /opt/lab/out/cm150/hello-cm.png
回显(实测):
0 0 1 122 0 0 0 189
0 0 2 79 0 0 1 39
默认 96dpi 得 378x189(0x017A、0x00BD),150dpi 得 591x295(0x024F、0x0127),与换算公式一致。
4.3 JPEG 质量:-q 与真实默认值
JPEG 质量梯度实测(同一 400x200 源):
ls -l /opt/lab/out/jq/hello.jpg /opt/lab/out/jq80/hello.jpg /opt/lab/out/jq30/hello.jpg | awk '{print $5, $9}'
回显(实测):
5050 /opt/lab/out/jq/hello.jpg
5486 /opt/lab/out/jq80/hello.jpg
3380 /opt/lab/out/jq30/hello.jpg
不带 -q 的默认输出(5050B)甚至小于 -q 0.8(5486B),因为不带 -q 时 Batik 不设置质量提示、JPEG 编码走 ImageIO 默认参数(内部消息键 jpeg.unspecifiedQuality);显式给 -q 才按给定质量编码。-q 的合法范围用越界值实测——传 -q 1:
java -jar /opt/batik/batik-rasterizer-1.19.jar -m image/jpeg -q 1 -d /opt/lab/out /opt/lab/hello.svg 2>&1 | grep -vE "^WARNING" | tail -5
回显(实测):
Error: illegal argument for option -q : 1
-q <quality> Quality for the generated output image. This is only used for JPEG conversion.
The value should be in the [0,1] range.
Example: -q 0.5
Default: 0.99
官方文案标注默认值 0.99、声称范围 [0,1],但实测 1 本身被拒绝(抛 IllegalArgumentException),实际可用的开区间是 0 < q < 1。
4.4 色深与背景:-indexed、-bg
-indexed 仅对 PNG 有效,把图像降为自适应调色板的索引色:
ls -l /opt/lab/out/hello.png /opt/lab/svg/hello.png | awk '{print $5, $9}'
回显(实测):
3544 /opt/lab/out/hello.png
5870 /opt/lab/svg/hello.png
同为 400x200 源,-indexed 8(256 色)产物 3544B,全彩 PNG 5870B,体积下降约 40%。-bg 255.255.235.205 以「透明像素替换色」形式为 JPEG(无透明通道)指定背景,格式为 a.r.g.b 四段整数。
4.5 CSS 与字体参数:-cssMedia、-cssAlternate、-cssUser、-font-family、-lang
这一组参数控制渲染期的 CSS 环境:-cssMedia 模拟目标媒介(screen/print 等)让 @media 规则按媒介分支;-cssAlternate 选择文档声明的 alternate stylesheet;-cssUser 追加一张用户样式表 URI;-font-family 为未声明 font-family 的文本指定兜底字体;-lang 按用户语言做 systemLanguage 条件渲染。均为 SVGAbstractTranscoder 对应提示键的命令行映射,实测与 -m 组合用法:
java -jar /opt/batik/batik-rasterizer-1.19.jar -cssMedia print -font-family "DejaVu Sans" -lang en -d /opt/lab/out-css /opt/lab/hello.svg
输出节选(实测):
Converting hello.svg to /opt/lab/out-css/hello.png ... ... success
4.6 校验与动画:-validate、-onload、-snapshotTime
-validate 让解析器按 DTD 校验源文件;-onload 决定是否先派发 onload 事件再渲染(涉及脚本执行与安全沙箱,详见第七章);-snapshotTime 把 SMIL 动画定位到指定时刻再截图,并隐含 -onload。
4.7 svgpp 与 ttf2svg 的参数默认值
svgpp(格式化工具)无参运行取官方默认值:
java -jar /opt/batik/batik-svgpp-1.19.jar 2>&1 | grep -E "doc-width|tab-width|newline|default"
输出节选(实测):
-doc-width <number>
Sets the document preferred number of columns. The default is 80.
-tab-width <number>
Sets the tabulation width. The default is 4.
-newline (cr | cr-lf | lf)
Specifies the type of newline to output. Possible values are:
cr (mac), cr-lf (dos), lf (unix - the default).
即 doc-width 默认 80、tab-width 默认 4、换行默认 lf。ttf2svg 的用法为 java org.apache.batik.svggen.font.SVGFont <ttf-path> [-l <range-begin>] [-h <range-end>] [-autorange] [-ascii] [-id <id>] [-o <output-path>] [-testcard](实测无参回显原文),不指定 -l/-h 时默认转换字体全部码位。
五、Transcoder 提示键详解(API 配置)
在 Java 代码里,rasterizer 的多数选项对应 Transcoder 的提示键(hint)。以下键均在本篇实测程序中验证或与命令行实测一一对应:
| 提示键 | 类 | 实测值与效果 |
|---|---|---|
PNGTranscoder.KEY_WIDTH / KEY_HEIGHT | PNGTranscoder | 800f/400f,输出 PNG 实测 800x400(IHDR 0x0320/0x0190) |
JPEGTranscoder.KEY_QUALITY | JPEGTranscoder | 0.8f,产物 5486B;缺省时走 ImageIO 默认质量(5050B) |
SVGAbstractTranscoder.KEY_AREA_OF_INTEREST | SVGAbstractTranscoder | 对应 rasterizer -a |
ImageTranscoder.KEY_BACKGROUND_COLOR | ImageTranscoder | 对应 rasterizer -bg |
SVGAbstractTranscoder.KEY_ALTERNATE_STYLESHEET | SVGAbstractTranscoder | 对应 -cssAlternate |
SVGAbstractTranscoder.KEY_USER_STYLESHEET_URI | SVGAbstractTranscoder | 对应 -cssUser |
SVGAbstractTranscoder.KEY_DEFAULT_FONT_FAMILY | SVGAbstractTranscoder | 对应 -font-family |
SVGAbstractTranscoder.KEY_WIDTH / KEY_HEIGHT | SVGAbstractTranscoder | PNG/JPEG/TIFF 共用的尺寸键 |
最小验证程序(Maven 工程 /opt/lab/batik-maven,依赖 batik-transcoder 1.19 + batik-codec 1.19):
package com.example;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.image.PNGTranscoder;
public class SvgToPng {
public static void main(String[] args) throws Exception {
TranscoderInput input = new TranscoderInput(
new File("/opt/lab/batik-maven/hello.svg").toURI().toString());
PNGTranscoder png = new PNGTranscoder();
png.addTranscodingHint(PNGTranscoder.KEY_WIDTH, 800f);
png.addTranscodingHint(PNGTranscoder.KEY_HEIGHT, 400f);
OutputStream out = new FileOutputStream("/opt/lab/batik-maven/hello-api.png");
png.transcode(input, new TranscoderOutput(out));
out.close();
System.out.println("PNG done -> hello-api.png");
}
}
编译运行与尺寸复核(实测):
PNG done -> hello-api.png
od -An -tu1 -j16 -N8 /opt/lab/batik-maven/hello-api.png
回显(实测):
0 0 3 32 0 0 1 144
⚠️ 注意:老资料提到的
XMLAbstractTranscoder.KEY_XML_PARSER_CLASS_NAME在 1.19 已不存在——实测代码引用该常量编译报cannot find symbol: variable KEY_XML_PARSER_CLASS_NAME。1.19 的解析器切换走系统属性(见第六章)。
💡 技术拓展:Transcoder 是按输出格式分族的类族,选型对比——
类 输出 关键专属键 PNGTranscoder PNG KEY_INDEXED(1~8 位索引色) JPEGTranscoder JPEG KEY_QUALITY(0~1 浮点) TIFFTranscoder TIFF KEY_COMPRESSION(压缩方式) PDFTranscoder 需另加 FOP pdf-transcoder 依赖 本篇实测采用 PNGTranscoder 与 JPEGTranscoder:PNG 覆盖透明与无损场景,JPEG 覆盖体积敏感场景,均为 batik-codec 内置、无需额外依赖。
六、XML 与 CSS 解析器配置(系统属性)
Batik 的解析器选择集中在 org.apache.batik.util.XMLResourceDescriptor。发行包内资源文件的内容实测如下:
cd /tmp && unzip -p /opt/batik/lib/batik-util-1.19.jar org/apache/batik/util/resources/XMLResourceDescriptor.properties | grep -vE "^#|^$"
回显(实测):
org.w3c.css.sac.driver = org.apache.batik.css.parser.Parser
即 CSS 解析器(SAC)默认用 Batik 自带的 org.apache.batik.css.parser.Parser。XML 侧则读取系统属性 org.xml.sax.driver,实测用 JDK 内置 Xerces 覆盖后转换正常:
cd /opt/lab/batik-maven && java -Dorg.xml.sax.driver=com.sun.org.apache.xerces.internal.parsers.SAXParser -cp target/classes:$(cat cp.txt) com.example.SvgToPng
回显(实测):
PNG done -> hello-api.png
JPEG done -> hello-api.jpg
不设该属性时 Batik 使用 JDK 默认 SAX 实现同样成功,说明此键是「可覆盖项」而非「必填项」。
💡 技术拓展:XML 解析器不止一种选择——
解析器 来历 特点 适用场景 JDK 内置 Xerces com.sun.org.apache.xerces.internal 零依赖、随 JVM 走 绝大多数部署(本篇实测默认) 独立 Xerces2 org.apache.xerces:xercesImpl 版本自控、可跟进安全修复 需要固定/升级解析器行为 其他 SAX2 实现 任意 org.xml.sax.XMLReader 只需实现标准接口 特殊嵌入环境 本篇按 1.19 默认行为使用 JDK 内置解析器,覆盖方法为
-Dorg.xml.sax.driver=实现类全名。
七、脚本与安全沙箱配置
Batik 在命令行工具启动时就会安装 Java SecurityManager(这是 JDK 17 出现废弃警告的原因),执行 SVG 内脚本(onload 等)时的安全边界由「脚本类型白名单 + 同源限制 + 策略文件」三层组成。以下链路全部实测。
第一步,准备带脚本的 SVG(onload 把背景色改为红色):
cat > /opt/lab/hello-script.svg << "SVGEOF"
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="200" viewBox="0 0 400 200"
onload="changeColor(evt)">
<rect id="bg" x="0" y="0" width="400" height="200" fill="#1e88e5"/>
<circle cx="80" cy="100" r="50" fill="#ffca28"/>
<text x="150" y="110" font-family="DejaVu Sans" font-size="32" fill="#ffffff">Hello Batik</text>
<script type="text/ecmascript"><![CDATA[
function changeColor(evt) {
var doc = evt.target.ownerDocument;
doc.getElementById("bg").setAttribute("fill", "#e53935");
}
]]></script>
</svg>
SVGEOF
回显(实测,写入成功无输出):
第二步,默认(无 -onload)不派发 onload,脚本不执行,输出与静态渲染完全一致(sha256 前 24 位实测 2bd7b2e091762e32015e7808)。
第三步,加 -onload 执行脚本。先记录一个发行包的真实缺陷——lib/ 里其实自带 Rhino(rhino-1.7.7.jar),但 rasterizer 应用 jar 的 MANIFEST Class-Path 只显式列了 16 个 jar、并未引用它,-jar 方式启动会缺类:
java -jar /opt/batik/batik-rasterizer-1.19.jar -onload -d /opt/lab/out2 /opt/lab/hello-script.svg 2>&1 | grep -vE "^WARNING" | head -2
输出节选(实测首部):
Converting hello-script.svg to /opt/lab/out2/hello-script.png ... Exception in thread "main" java.lang.NoClassDefFoundError: org/mozilla/javascript/WrapFactory
at org.apache.batik.bridge.RhinoInterpreterFactory.createInterpreter(RhinoInterpreterFactory.java:82)
ls /opt/batik/lib/ | grep rhino
回显(实测):
rhino-1.7.7.jar
第四步,改用主类方式、把 lib/ 全部 jar 放进类路径(-jar 模式会忽略 -cp,这是 Java 的固定行为),让自带的 Rhino 1.7.7 被加载:
cd /opt/batik && java -cp "batik-rasterizer-1.19.jar:lib/*" org.apache.batik.apps.rasterizer.Main -onload -d /opt/lab/out2 /opt/lab/hello-script.svg 2>&1 | grep -vE "^WARNING" | tail -3
回显(实测收尾段):
Caused by: java.security.AccessControlException: access denied ("java.util.PropertyPermission" "rhino.stack.style" "read")
at java.base/java.security.AccessControlContext.checkPermission(AccessControlContext.java:1068)
这就是沙箱在工作:Batik 按内置策略资源(jar 内 org/apache/batik/apps/rasterizer/resources/rasterizer.bin.policy)安装 SecurityManager。策略给 lib/ 各 Batik 模块全权限,但对脚本引擎的白名单条目写的是旧文件名 lib/js.jar(限 createClassLoader、Socket、两个特定 PropertyPermission、文件读),而 1.19 实际捆的是 rhino-1.7.7.jar——文件名对不上、授权落空,Rhino 1.7.x 初始化时读系统属性 rhino.stack.style 即被拒。实测该拦截与 Rhino 版本无关:换用 1.7.14、1.7R5、1.7.15 放在类路径首位全部同报错,证明拦截来自策略而非某个 Rhino 版本缺陷。
第五步,-scriptSecurityOff 关闭沙箱再跑(这次暴露的是更深一层的问题——Batik 1.19 的全局包装脚本与 Rhino 全系不兼容):
cd /opt/batik && java -cp "batik-rasterizer-1.19.jar:lib/*" org.apache.batik.apps.rasterizer.Main -onload -scriptSecurityOff -d /opt/lab/out2 /opt/lab/hello-script.svg 2>&1 | grep -vE "^WARNING" | tail -4
回显(实测收尾段):
ERROR: null
Enclosed Exception:
Function importClass must be called with a class; had "[JavaPackage org.w3c.dom.DOMImplementationSource]" instead.
... success
渲染流程走完(success),但 onload 回调实际未生效——产物 sha256 前 24 位仍为 2bd7b2e091762e32015e7808,与第二步静态渲染基线完全一致。把类路径首位分别换成 rhino-1.7.14、1.7R5、1.7R4 复测,全部倒在同一个 importClass 错误上。根因:Batik 初始化脚本解释器时先执行一段全局包装脚本(内含 importClass 等桥接函数),1.19 的这段包装脚本与 Rhino 1.7 全系在 JavaPackage 成员解析行为上不匹配。结论与建议:生产上以「Transcoder API 静态渲染 + 不派发脚本」为主;确需脚本执行时,必须先在目标版本组合下实测验证(1.19 + Rhino 1.7 全系实测均不可用),并关注官方版本公告。
第六步,验证 Transcoder API 的脚本边界:用 Maven 工程(已含 rhino 1.7.15 依赖)对同一文件分别带/不带 Rhino 渲染,产物哈希实测完全一致(均为 2bd7b2e091762e32015e7808)——Transcoder API 是静态渲染,不派发 onload 事件,脚本要执行必须走 rasterizer -onload 或 JSVGCanvas 动态环境。
💡 技术拓展:Batik 支持的脚本引擎不止 ECMAScript 一种——
引擎 类型 依赖 ECMAScript(Rhino) text/ecmascript、application/javascript 发行包 lib/ 自带 rhino-1.7.7.jar(MANIFEST 未引用,且与 1.19 包装脚本不兼容,见本章实测) Jacl(Tcl) text/tcl jacl 包,另行添加 JPython text/python jython 包,另行添加 引擎由
<script type="...">的 type 触发、由 batik-script 内的 InterpreterFactory 探测类路径决定;本篇实测以 ECMAScript/Rhino 为主线(最常见)。
策略层面还有两个开关:-scripts <列表> 白名单允许的脚本类型(如 -scripts text/ecmascript),-anyScriptOrigin 允许脚本从任意位置加载(默认仅允许与文档同源)。三者与 -scriptSecurityOff 的取舍:能白名单就不关沙箱,测试调试才用 -scriptSecurityOff。
八、Squiggle 浏览器配置
Squiggle 是 Batik 自带的 Swing SVG 浏览器(batik-squiggle-1.19.jar),无显示环境直接启动会报错(实测):
java.awt.HeadlessException:
No X11 DISPLAY variable was set,
or no headful library support was found,
but this program performed an operation which requires it.
可运行的前提有两条:JDK 带图形支持(headful 本地库)、存在可用的 X 显示。配置项(窗口布局、缩放、脚本安全选项等)由 Swing 菜单操作,持久化走 JVM 标准的 java.util.prefs 机制(Linux 落在用户主目录 ~/.java/.userPrefs 下,首次保存偏好时生成)。服务器场景一般不用 Squiggle,其安全设置与 rasterizer 同源(同样受 -scriptSecurityOff 对应的选项与策略资源约束)。
九、生产配置模板
按场景给出可直接套用的推荐参数集:
场景一:Web 服务端批量 SVG 转 PNG(4 核 8GB、SSD、日均百万级小图)
java -Xms256m -Xmx512m -jar /opt/batik/batik-rasterizer-1.19.jar \
-m image/png -w 1024 -h 1024 -indexed 8 -d /data/out /data/svg
要点:堆 256–512MB(单机多进程并行转换时每进程 256MB 更稳);-indexed 8 在可接受色损下显著省存储;输出目录与源分离。
场景二:归档截图、画质优先(16GB 内存、NVMe)
java -Xms256m -Xmx512m -jar /opt/batik/batik-rasterizer-1.19.jar \
-m image/jpeg -q 0.95 -bg 255.255.255.255 -font-family "DejaVu Sans" -d /data/out /data/svg
要点:JPEG 显式给 -q 0.95(不给出 ImageIO 默认质量);-bg 消除透明区黑块风险;-font-family 统一兜底字体避免各机渲染差异。
场景三:Java 服务内嵌渲染(Spring 等常驻 JVM)
-Xms256m -Xmx512m
PNGTranscoder.KEY_WIDTH/KEY_HEIGHT 显式设定
JPEGTranscoder.KEY_QUALITY 显式设定
不派发脚本(Transcoder 本身静态)
要点:常驻进程用 -Xmx512m 封顶转换峰值;所有提示键显式化,避免依赖 ImageIO 默认值;系统属性 -Dorg.xml.sax.driver 仅在需要固定解析器时设置。
十、常见问题(FAQ)
Q1:找不到 batik.properties,配置文件到底在哪?
不存在。实测全部 jar 检索无 batik.properties 字样(见第三章)。配置走命令行参数、Transcoder 提示键、系统属性与内置策略资源四类入口。
Q2:-help 为什么报错?
rasterizer 无帮助选项,无参运行才是选项表;-help 被当成文件名(实测报错见第四章开头)。
Q3:-dpi 150 不生效?
dpi 只缩放带物理单位(cm/mm/in/pt)的文档;无单位像素文档不受影响(实测对照见 4.2 节表格)。
Q4:-q 1 报 IllegalArgumentException?
官方文案写 [0,1] 但实测 1 被拒,实际取开区间 0 < q < 1,如 -q 0.99(文案标注默认 0.99)。
Q5:脚本为什么会触发 AccessControlException?
Batik 默认沙箱按内置策略限制脚本权限。1.19 实测的直接诱因是内置策略白名单写的 lib/js.jar 与实捆的 rhino-1.7.7.jar 文件名不匹配(授权落空),新版 Rhino 初始化读 rhino.stack.style 属性即被拒(见第七章)。处理路径:改为静态渲染,或白名单脚本类型,调试期才 -scriptSecurityOff——注意 1.19 关沙箱后脚本仍因 importClass 不兼容而不生效。
Q6:Transcoder 代码里找不到 KEY_XML_PARSER_CLASS_NAME?
1.19 已移除该提示键(实测编译 cannot find symbol),用 -Dorg.xml.sax.driver=... 系统属性替代。
十一、参考链接
- 官方 Rasterizer 文档:https://xmlgraphics.apache.org/batik/tools/rasterizer.html
- 官方 Transcoder 文档:https://xmlgraphics.apache.org/batik/using/transcoder.html
- 官方 SVG 浏览器(Squiggle)文档:https://xmlgraphics.apache.org/batik/tools/browser.html
- 官方安全公告页:https://xmlgraphics.apache.org/batik/security.html
- Maven 中央仓库 batik-transcoder:https://central.sonatype.com/artifact/org.apache.xmlgraphics/batik-transcoder