自定义图像转码器
编写一个可以读取 SVG 文件并将该资源转换为 PNG 或 SVG 文件的自定义图像转码器。导出为 PDF 时,可以直接使用 SVG 文件。考虑:
import java.awt.Color;
import java.io.*;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.util.JRLoader;
import org.apache.batik.transcoder.*;
import static org.apache.batik.transcoder.image.ImageTranscoder.*;
import org.apache.batik.transcoder.image.PNGTranscoder;
public class ImageTranscoder {
public static InputStream asSVG(final String file) throws JRException {
return new ByteArrayInputStream(load(file));
}
public static InputStream asPNG(final String file)
throws TranscoderException, JRException {
return asPNG(load(file));
}
public static InputStream asPNG(final byte[] svg)
throws TranscoderException {
final ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
final ByteArrayInputStream inBytes = new ByteArrayInputStream(svg);
final TranscoderInput input = new TranscoderInput(inBytes);
final TranscoderOutput output = new TranscoderOutput(outBytes);
final PNGTranscoder transcoder = new PNGTranscoder();
transcoder.addTranscodingHint(KEY_BACKGROUND_COLOR, Color.white);
transcoder.addTranscodingHint(KEY_FORCE_TRANSPARENT_WHITE, true);
transcoder.transcode(input, output);
final byte[] bytes = outBytes.toByteArray();
return new ByteArrayInputStream(bytes);
}
private static byte[] load(final String file) throws JRException {
return JRLoader.loadBytesFromResource(file);
}
}
导入转码器
在 JRXML 文件中,导入全限定类:
<import value="com.company.jasper.ImageTranscoder"/>
应用图像转码器
照常将图像从调色板拖放到报表上。将其表达式设置为:
ImageTranscoder.asSVG($P{IMAGES_PATH} + $P{IMAGE_FILENAME} + ".svg")
如果您绝对需要 PNG 版本,请即时转码:
ImageTranscoder.asPNG($P{IMAGES_PATH} + $P{IMAGE_FILENAME} + ".svg")
HTML 与 PDF
对于 HTML,通常仍首选 PNG 图像。您可以采用多种方法来区分 HTML (PNG) 和 PDF (SVG)。一种简单的方法是将两个不同的键值分配给两个不同的 Image 元素。例如:
<image scaleImage="RetainShape" onErrorType="Blank">
<reportElement key="IMAGE_PNG"/>
<imageExpression><![CDATA[ImageTranscoder.asPNG(...)]]></imageExpression>
</image>
<image scaleImage="RetainShape" onErrorType="Blank">
<reportElement key="IMAGE_SVG"/>
<imageExpression><![CDATA[ImageTranscoder.asSVG(...)]]></imageExpression>
</image>
然后您可以根据导出类型排除其中一个:
<property name="net.sf.jasperreports.export.html.exclude.key.IMAGE_SVG"/>
<property name="net.sf.jasperreports.export.pdf.exclude.key.IMAGE_PNG"/>
总结
虽然包含 PNG 图像更简单,但从 SVG 转换该 PNG 图像是可以避免的额外步骤。由于 JasperReports 库使用 Batik 引擎来呈现图像,因此在生成报告时利用它来将 SVG 文件转换为 PNG。
这样,SVG 可作为所有格式的单一来源,无论报告中使用的是 PNG 还是 SVG 文件。
请务必根据需要设置IMAGES_PATH 和IMAGE_FILENAME 参数。
HTML 和 Base64
使用以下命令强制嵌入图像:
<property name="net.sf.jasperreports.export.html.embed.image" value="true"/>
PNG 图像变成 Base64 编码的字符串:
<img src="data:image/png;base64,..."/>
这将使报告加载速度更快一些(无需对图像进行额外的 HTTP 请求)并简化架构,因为它消除了外部依赖。也就是说,不再需要网络服务器来提供图像,因为它是完全嵌入的。