如何在 JasperReport 中将 svg 字节数组显示为图像? [英] How to display a svg byte array as an image in a JasperReport?

查看:21
本文介绍了如何在 JasperReport 中将 svg 字节数组显示为图像?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have an image saved as a byte[] and I would like to display it as an image in a JasperReport. I have tried getting the data from Java methods:

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

但它们似乎都不起作用.

but none of them seem to be working.

jrxml 看起来像这样:

The jrxml looks like this:

<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数据.

Some of things I try get exceptions and some print the JasperReport but the area where the image is supposed to be is blank. I know the image data is there because I can display it in a JSF page. The image data is SVG data.

推荐答案

Custom Image Transcoder

编写一个自定义图像转码器,可以读取 SVG 文件并将该资源转换为 PNG 或 SVG 文件.导出为 PDF 时,可以直接使用 SVG 文件.考虑:

Custom Image Transcoder

Write a custom image transcoder that can read an SVG file and transform that resource into a PNG or SVG file. When exporting as PDF, it is okay to use an SVG file directly. Consider:

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 Transcoder

In the JRXML file, import the fully qualified class:

<import value="com.company.jasper.ImageTranscoder"/>

应用图像转码器

像往常一样,将图像从调色板拖放到报告上.将其表达式设置为:

ImageTranscoder.asSVG($P{IMAGES_PATH} + $P{IMAGE_FILENAME} + ".svg")

如果您绝对需要 PNG 版本,请即时对其进行转码:

If you absolutely need a PNG version, then transcode it on-the-fly:

ImageTranscoder.asPNG($P{IMAGES_PATH} + $P{IMAGE_FILENAME} + ".svg")

HTML 与 PDF

对于 HTML,通常仍首选 PNG 图像.您可以采用多种方法来区分 HTML (PNG) 和 PDF (SVG).一种简单的方法是将两个不同的键值分配给两个不同的 Image 元素.例如:

HTML vs PDF

With HTML, typically PNG images are still preferred. There are a number of approaches you can take to differentiate HTML (PNG) from PDF (SVG). A simple way is to assign two different key values to two different Image elements. For example:

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

然后您可以根据导出类型排除其中一个:

Then you can exclude one or the other based on the export type:

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

Summary

While it is simpler to include a PNG image, converting that PNG image from SVG is an additional step that can be avoided. Since the JasperReports Library uses the Batik engine for rendering images, leverage it to convert an SVG file to PNG when the report is generated.

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

This way, the SVG serves as a single source for all formats, regardless of whether a PNG or SVG file is used in the report.

请务必根据需要设置 IMAGES_PATHIMAGE_FILENAME 参数.

Be sure to set the IMAGES_PATH and IMAGE_FILENAME parameters as appropriate.

强制嵌入图像:

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

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

The PNG image becomes a Base64-encoded String:

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

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

This will make the report load a bit faster (no extra HTTP request for the image) and simplify the architecture as it eliminates an external dependency. That is, a web server is no longer required to serve the image, since it is wholly embedded.

这篇关于如何在 JasperReport 中将 svg 字节数组显示为图像?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆