在JasperReport中将字节数组显示为图像

时间:2015-11-05 14:48:27

标签: java jasper-reports bytearray

我将图片保存为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数据。

6 个答案:

答案 0 :(得分:5)

自定义图像转码器

编写可以读取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 Library使用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服务器来提供图像,因为它是完全嵌入的。

答案 1 :(得分:3)

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

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

答案 2 :(得分:1)

  

你可以试试这个:

将您的图片参数(此处为 img )设置为 InputStream

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

然后将 onErrorType =&#34;空白&#34; 设置为您的图片元素(实际上不知道原因:))

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

答案 3 :(得分:1)

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

我们必须建立以下导入:

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

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

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

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

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

就是这样。该解决方案如何运作?我们导入javax.swing.ImageIcon库,允许我们从byte[]创建新的ImageIcon,然后我们可以使用ImageIconImage转换为getImage()。< / p>

答案 4 :(得分:0)

getImage()应该返回字节[]

在您的jasperreports模板中看不到paramObject是什么类型,但是应该是String

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

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

答案 5 :(得分:-1)

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

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

     

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