gpt4 book ai didi

java - 如何在 JasperReport 中将 svg 字节数组显示为图像?

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:58:21 32 4
gpt4 key购买 nike

我有一张保存为 byte[] 的图像,我想在 JasperReport 中将其显示为图像。我尝试从 Java 方法获取数据:

public InputStream getImage(){
return new ByteArrayInputStream(getImageByteArray());
}

public Image getImage() throws IOException{
return ImageIO.read(new ByteArrayInputStream(getImageByteArray()));
}

public String getImage(){
return new String((new org.apache.commons.codec.binary.Base64()).encode(getImageByteArray()));
}

但它们似乎都不起作用。

jrxml 看起来像这样:

<image hAlign="Center" vAlign="Middle" isUsingCache="true" isLazy="true">
<reportElement positionType="Float" x="0" y="0" width="164" height="32" isRemoveLineWhenBlank="true" isPrintWhenDetailOverflows="true" uuid="c63c84a8-41c7-4ca3-8451-751d43fa8a9e"/>
<imageExpression><![CDATA[$P{paramObject}.getImage()]]></imageExpression>
</image>

我尝试的一些事情会出现异常,一些会打印 JasperReport,但图像应该位于的区域是空白的。我知道图像数据在那里,因为我可以在 JSF 页面中显示它。图片数据为SVG数据。

最佳答案

自定义图像转码器

编写一个可以读取 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"/>

应用图像转码器

像往常一样,将图像从调色板拖放到报告中。将其 Expression 设置为:

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 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。

这样,无论报告中使用的是 PNG 还是 SVG 文件,SVG 都可以作为所有格式的单一来源。

一定要适本地设置 IMAGES_PATHIMAGE_FILENAME 参数。

HTML 和 Base64

使用以下方法强制嵌入图像:

<property name="net.sf.jasperreports.export.html.embed.image" value="true"/>

PNG 图像变成 Base64 编码的字符串:

<img src="data:image/png;base64,..."/>

这将使报告加载速度更快(没有额外的 HTTP 图像请求)并简化架构,因为它消除了外部依赖性。也就是说,不再需要 Web 服务器来提供图像,因为它是完全嵌入式的。

关于java - 如何在 JasperReport 中将 svg 字节数组显示为图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33547588/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com