We’re adding XML datasources for reports in RightsPro (currently JasperReports is supported) and needed to embed the image data directly in the XML so thought I’d expand on the solution I found here.
If your creating your XML dynamically using Java you can do:
...
import org.apache.commons.codec.binary.Base64;
// Read the byte array from DB or whatever
byte[] imageByteArray = getImageByteArray();
String base64Image = Base64.encodeBase64String(imageByteArray);
...
then write the Base64 encoded data in your XML as:
...
<image><![CDATA[ ... Base64 mess here ... ]]></image>
...
The rest comes from this JasperForge forum post which explains how to decode the Base64 into a ByteArrayInputStream
that’s usable by the JasperReports image report element.
As the post says, in your JasperReport (we currently use iReport as a report editor) define a String field, let’s call it Image
, for the image:
then define a variable, let’s call it ImageBytes
, which uses that field:
with the Variable Expression:
new ByteArrayInputStream(new Base64().decodeBase64($F{Image}.getBytes("UTF-8")))
(don’t forget to add org.apache.commons.codec.binary.Base64
to the imports of the report properties)
and in the image element on your layout use the ImageBytes variable:
and you should see your image properly rendered in the final report.
However, what I found at this point is that while the images displayed fine in iReport in PDF preview most PDF readers were unable to display the images, resulting in just a black rectangle.
The solution was to change the ImageBytes
variable class to java.awt.Image
with a constructor of:
ImageIO.read(new ByteArrayInputStream(new Base64().decodeBase64($F{Image}.getBytes("UTF-8"))))
then change the expression class of the image element on the layout to java.awt.Image
as well. You’ll also have to add javax.imageio.ImageIO
to the imports of the report.
This technique can be useful when you need to grab the image data dynamically (not from actual files on the filesystem), you can’t get each image from a URL (perhaps due to security constraints), and don’t want to use a custom Java datasource.