Skip to main content
Blog

Embedding images with Pojo BIRT Runtime

By 13 juni 2013januari 30th, 2017No Comments

In a previous blog post I created a skeleton class for rendering a report using BIRT runtime. You can pass it the report parameters, the report definition (rptdesign) and an OutputStream and it will render HTML  to that stream.

 

If your report definition contains graphs we run into a problem. Normally, in HTML an image is a separate resource. BIRT will generate the images containing your graphs in a temporary directory and will link to them in your HTML. For this to work, you will have to configure the Platform to write the images to a publicly accessible directory and write the links using the correct domains. Furthermore, you’ll probably need some process to clean up the images after the reports have been viewed. If your reports are being used in some website and generated on the fly, this is most likely quite difficult to determine. Maybe when the user logs out?

Luckily, in modern browsers we can embed the images in the same stream, bypassing the need of a temporary directory. The following trick will encode the image with base64 and embed it directly into the HTML stream using css data . This will work on most modern browsers but of course Internet Explorer lags a bit behind. PNG support is available up until 32kb in Internet Explorer 8 and SVG not at all. Internet Explorer 9 works fine, as well as the other major browsers.

So how does it work? First, we explicitly tell the render engine to use PNG or SVG. SVG provides sharper images but will not work in Internet Explorer 8 as mentioned above. Next, we inject our own HTMLServerImageHandler which encodes the image data to base64.

    private HTMLRenderOption getHtmlRenderOptions(OutputStream outs) {
        // set render options including output type
        HTMLRenderOption options = new HTMLRenderOption();
        options.setOutputStream(outs);

        if (USE_SVG) {
            options.setSupportedImageFormats("SVG");
        } else {
            options.setSupportedImageFormats("PNG");
        }
        setupImageHandler(options);
        options.setEmbeddable(true);
        options.setOutputFormat("html");
        return options;
    }

    private void setupImageHandler(final HTMLRenderOption options) {
        options.setImageHandler(new HTMLServerImageHandler() {
            @Override
            protected String handleImage(IImage image, Object context, String prefix, boolean needMap) {
                String embeddedImage = Base64.encode(image.getImageData(), false);
                return "data:" + image.getMimeType() + ";base64," + embeddedImage;
            }
        });
    }

Some references: