How to render a internal image on a swing component using html?

html, java, swing

Solution

I had to rewrite one of the Java classes and extend another, but got the BASE64 image working under HTML on the JEditorPane. I'll post my solution in case someone needs it in the future...

First, create a Special HTMLEditorKit that will use the rewritten ImageView class for the HTML.Tag.IMG

class BASE64HTMLEditorKit extends HTMLEditorKit {

    private static HTMLFactory factory = null;

    @Override
    public ViewFactory getViewFactory() {
        if (factory == null) {
            factory = new HTMLFactory() {

                @Override
                public View create(Element elem) {
                    AttributeSet attrs = elem.getAttributes();
                    Object elementName = attrs.getAttribute(AbstractDocument.ElementNameAttribute);
                    Object o = (elementName != null) ? null : attrs.getAttribute(StyleConstants.NameAttribute);
                    if (o instanceof HTML.Tag) {
                        HTML.Tag kind = (HTML.Tag) o;
                        if (kind == HTML.Tag.IMG) {
                            // HERE is the call to the special class...
                            return new BASE64ImageView(elem);
                        }
                    }
                    return super.create(elem);
                }
            };
        }
        return factory;
    }

}

With that done, implement the special class, based on the openjdk code. Download the source code here, and open the file openjdk/jdk/src/share/classes/javax/swing/text/html/ImageView.java. Because it have almost everything private, I found it easier to copy it entirely and then change the method needed to load BASE64 Images:

private void loadImage() {
    String b64 = getBASE64Image();
    BufferedImage newImage = null;
    try (ByteArrayInputStream bais = new ByteArrayInputStream(DatatypeConverter.parseBase64Binary(b64))) {
        newImage = ImageIO.read(bais);
    } catch (IOException ex) {
        ...
    }
    image = newImage;
}

private String getBASE64Image() {
    String src = (String) getElement().getAttributes().getAttribute(HTML.Attribute.SRC);
    if (src == null) {
        return null;
    }
    return src.replaceFirst("data:image/png;base64,", "");
}

The getBASE64Image method just cuts the non BASE64 part of the attribute. The loadImage method is the one that has to be changed, and if it where public, would have helped cut a lot of code from the solution...

If someone has a better and preferably smaller (mine have 1000 lines of code), please share it...

Problem

I have the following code: ``` public static void main(String[] args) { JFrame frm = new JFrame(); JEditorPane pane = new JEditorPane("text/html", "<html><body>test<br><img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACuklEQVR42sWVv09TURTH71AXE40xaRdXEwbD4ODiIFr6EwcXN1cnR0cXoyTWUjcH3n0dDG4aEwcaoqggWn8ERWtoKdVBoA2lxbj4BxzPt+eaPEn7nhDeleRDTr733vP9vtvXU0VE6n8i//79L5KdUKVUXtHobUXxnIAaGtawZzcNdxvgEIw2u0Va39SMa9A9DWvYE2aAKJ4WhpPTipySgBoa1rAnzAAxXPnalkvOjCL3iYAaGtawJ/QA650iaTYuPhVQQ7MbAOazAmqrAdb4hXOe8fW/EFBDsxdgmwM8Z/M5ATU0ewF+cACYvxRQQ7MS4NwtRd9xA/NsviCghoa1vQaIjP2ZcLnBxNng9E1F37p3yYH5awE1NKxhj18PeIx5J6YJ0Jtwaz/vUKObZwoDqW8VaL5xkfQr/gaUBdTQsOZ3Fr3h8dfENAGiCU5X79ygSW7oBKDf8JO/ZXMDamhB59AbHomcZ2KaADGIy+1r5HAjjabv+lMMYNA59ERveCS8L6s3QKV9lRxsfs+H9hn0RG94DAyw1L5CepEPfOCn8cFd7I/vGQa94dE3QJpfjMr2ZZr6oui+D/c+c8OP0tALNKz5nUVveKTzfQKcL6hfmQnVWxxEin9uR8YVlVuXSC+xsQE1NKxhj18PeCSuq/LOl/AIc5KJM6M+ZHB9C60LpD+xuQE1NHO1mYAeI8yJnV/DAyZELIChJJvMtVKkK2xuQA0tKQGGAnpEjXlkT6M4xSazzTPk8ufpBVrKxm8BTGaap8itsvGyoSqatQCljWFya2LcoyaatQCPW8dJr/BnXzOsiGYtwKPmMdKrbFw3rIpmJUCaTR60jlLxK199Q0ANLW0jQJaHycPOQZpq8mTbMDRFy+bDDxDNjKsqjPC0XqAlvRMupACHmWHmbOCECylAxISIBk64kALs+99vkl5XSNCDZhMAAAAASUVORK5CYII=\"></body></html>"); pane.setEditable(false); frm.getRootPane().setContentPane(pane); frm.pack(); frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frm.setVisible(true); } ``` What I'm trying to do is render a image on the JEditorPane using base64 codification to store the image. It does not need to be base64, but that's as far as I got while trying to render HTML content on the JEditorPane, but I need to use an image that is on a BufferedImage(It is generated by the application.), and, would really prefer not to have to save the image to a file in the hard disk. Can I, somehow, display an BufferedImage in a swing component along with HTML(displaying it in the place given by the IMG tag - the html code is generated by the application too)?

Original source