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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33547588/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 21:50:31  来源:igfitidea点击:

How to display a svg byte array as an image in a JasperReport?

javaarrayssvgjasper-reports

提问by cbender

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:

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

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

and

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

and

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

but none of them seem to be working.

但他们似乎都没有工作。

The jrxml looks like this:

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>

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.

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

回答by Dave Jarvis

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:

编写一个自定义图像转码器,可以读取 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);
    }
}

Import Transcoder

导入转码器

In the JRXML file, import the fully qualified class:

在 JRXML 文件中,导入完全限定的类:

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

Apply Image Transcoder

应用图像转码器

Drag and drop an Image from the palette onto the report, as per usual. Set its Expressionto:

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

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

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

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

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

HTML vs PDF

HTML 与 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:

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

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

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.

虽然包含 PNG 图像更简单,但从 SVG 转换该 PNG 图像是一个可以避免的附加步骤。由于 JasperReports 库使用 Batik 引擎来渲染图像,因此在生成报告时利用它来将 SVG 文件转换为 PNG。

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.

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

Be sure to set the IMAGES_PATHand IMAGE_FILENAMEparameters as appropriate.

请务必适当设置IMAGES_PATHIMAGE_FILENAME参数。

HTML and Base64

HTML 和 Base64

Force the image to embed using:

使用以下命令强制嵌入图像:

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

The PNG image becomes a Base64-encoded String:

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

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

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.

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

回答by Aram Arabyan

Assuming that you have image bytes encoded base64, you can use following

假设您有 base64 编码的图像字节,您可以使用以下

<image>
    <reportElement/>
    <imageExpression>
        <![CDATA[javax.imageio.ImageIO.read(new java.io.ByteArrayInputStream(new sun.misc.BASE64Decoder().decodeBuffer("/9j/4AAQ .... "))) ]]>
    </imageExpression>
</image>

回答by Madushan Perera

You can try this :

你可以试试这个:

Set your image parameter (here it is img) to InputStream

将您的图像参数(这里是img)设置为InputStream

<parameter name="img" class="java.io.InputStream">
        <parameterDescription><![CDATA[]]></parameterDescription>
    </parameter>

Then set onErrorType="Blank"to your image element(Actually dont know the reason to this :) )

然后将onErrorType="Blank" 设置为您的图像元素(实际上不知道这样做的原因:))

<image onErrorType="Blank">
    <reportElement x="2" y="4" width="119" height="62" uuid="66857471-6aa2-4ff0-be59-e2e1b0214bfc"/>
    <imageExpression><![CDATA[$P{img}]]></imageExpression>
</image>

回答by cesAR

I propose a simple solution. It works, I'm using it. This way we avoid intermediate code and modifications to our application.

我提出了一个简单的解决方案。它有效,我正在使用它。这样我们就可以避免中间代码和对应用程序的修改。

We must establish the following Import:

我们必须建立以下导入:

<import value="javax.swing.ImageIcon"/>

The definition of our field for the image must be of type Objet:

图像字段的定义必须是 Objet 类型:

<field name="myImage" class="java.lang.Object"/>

And then in the body of the report, we must place the image with the following expression:

然后在报告正文中,我们必须放置具有以下表达式的图像:

<image>
  <reportElement x="10" y="10" width="100" height="100" uuid="a791129e-a20d-4be3-bdcd-27528bf2edc4"/>
  <imageExpression><![CDATA[(new ImageIcon((byte[])$F{foto})).getImage()]]></imageExpression>
</image>

That is all. How does the solution work? We import the javax.swing.ImageIconlibrary, which allows us to create a new ImageIcon from a byte[], then we can convert an ImageIconto Imageusing getImage().

就这些。解决方案如何运作?我们导入javax.swing.ImageIcon库,它允许我们从 a 创建一个新的 ImageIcon byte[],然后我们可以将 an 转换ImageIconImageusing getImage()

回答by whoisacat

getImage() should return byte[]

getImage() 应该返回 byte[]

I can't see what type is paramObject in your jasperreports template, but it should be String

我看不到你的 jasperreports 模板中的 paramObject 是什么类型,但它应该是 String

And the easiest way to deserialize pic without any unavailable oracle libraries is:

在没有任何不可用的 oracle 库的情况下反序列化 pic 的最简单方法是:

<imageExpression><![CDATA[javax.imageio.ImageIO.read(new java.io.ByteArrayInputStream(java.util.Base64.getDecoder().decode($F{paramObject})))]]></imageExpression>

回答by tamkhade mahesh

The definition of our field for the image must be of type Objet:

图像字段的定义必须是 Objet 类型:

And then in the body of the report, we must place the image with the following expression:

然后在报告正文中,我们必须放置具有以下表达式的图像:

this code is work for me....

这段代码对我有用....