显示base64编码的图像

A. *_*ork 2 html java jtextpane

我在将图像集成到 text/html JTextPane 时遇到问题。JTextPane 使用以下文本初始化:

<html>
  <head>
    <style type="text/css">
    </style>
  </head>
  <body>
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

我插入文本:

kit.insertHTML(doc, doc.getLength(), "<b>" + string + "</b><br>" , 0, 0, HTML.Tag.B);
Run Code Online (Sandbox Code Playgroud)

以这种方式插入的所有文本都会正确显示,但是当我尝试使用以下命令插入 base64 编码的图像时:

kit.insertHTML(doc,doc.getLength(), "<img src=\"data:image/jpeg;base64," + base64Code + "\"/>", 0, 0, HTML.Tag.IMG);
Run Code Online (Sandbox Code Playgroud)

我只得到了一个占位符图像。当尝试使用正常的源路径时,它起作用了。然而,在线获取 Base64 代码并使用它也为我提供了一个占位符图像,而完全相同的代码可以在 w3school.com 的 HTML tryit 编辑器上运行。

Ali*_*yhl 6

当 aJTextPane看到一个<img>标签时,它会检查缓存中是否存在该图像,如果不存在,它将尝试从 url 中读取该图像。使用的html库JTextPane不支持<img>标签中base64编码的图像数据,因此我们需要以不同的方式进行处理。

原来我们可以手动将图片添加到图片缓存中。这可以用来选择一些无效的 URL 并为其分配一个图像。


让我们将图像添加到缓存并在JTextPane!

首先,您要将图像转换为BufferedImage. 这可以使用类来完成ImageIO

byte[] imgBytes = decodeBase64(base64Code);
BufferedImage img = ImageIO.read(new ByteArrayInputStream(imgBytes));
Run Code Online (Sandbox Code Playgroud)

请注意,这里我们需要原始图像字节,而不是 base64 编码。如果您正在从文件中读取图像,则可以将 a 传递Fileread函数而不是输入流。


现在我们有了 a 图像BufferedImage,我们可以编写一个函数将其添加到缓存中。

@SuppressWarnings({ "rawtypes", "unchecked" })
public static String saveImageToCache(JTextPane pane, BufferedImage img, String name) throws MalformedURLException {
    Dictionary cache = (Dictionary) pane.getDocument().getProperty("imageCache");
    if (cache == null) {
        // No cache exists, so create a new one.
        cache = new Hashtable();
        pane.getDocument().putProperty("imageCache", cache);
    }
    String url = "http:\\buffered/" + name;
    cache.put(new URL(url), img);
    return url;
}
Run Code Online (Sandbox Code Playgroud)

Dictionary请注意,我抑制了有关和上的类型参数的一些警告Hashtable。通常应该避免这种情况,但在这种情况下,我们正在以可以抑制警告的方式处理 Swing 废话。

此方法本质上是选择一些无效的 url 并将图像存储在该 url 中。

注意name论证。这将是 url 的一部分,如果您尝试将与前一张图像同名的图像存储到缓存中,这将替换前一张图像。避免在此名称中使用疯狂的字符,因为如果它不是有效的 url,new Url(url)可能会抛出 a 。MalformedURLException


我们现在可以将它与 一起使用JTextPane

BufferedImage img = ...;

JTextPane pane = new JTextPane();
pane.setContentType("text/html");

String url = saveImageToCache(pane, img, "image1");

pane.setText("<html><body><img src=\"" + url + "\"></body></html>");

JFrame frame = new JFrame("image test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(pane);
frame.setSize(img.getWidth(), img.getHeight());
frame.setLocationRelativeTo(null);
frame.setVisible(true);
Run Code Online (Sandbox Code Playgroud)

请注意,您必须setContentType在将图像添加到缓存之前调用,因为该方法会清除缓存。此外,在调用之前将图像添加到缓存中非常重要setText,以确保在 swing 需要图像之前添加图像。

如果使用先前已知的名称更改了缓存中的图像saveImageToCache,则需要JTextPane以某种方式更新,例如调用setText.


如果您有大量图像,您可能希望在不再需要它们时将它们从缓存中删除,以避免过多的内存使用。实现此目的的一种方法是定义一个如下所示的函数,该函数从缓存中删除图像。

@SuppressWarnings({ "rawtypes" })
public static void removeImageFromCache(JTextPane pane, String name) throws MalformedURLException {
    Dictionary cache = (Dictionary) pane.getDocument().getProperty("imageCache");
    if (cache == null) {
        // There is no cache, so the image is not in the cache.
        return;
    }
    String url = "http:\\buffered/" + name;
    cache.remove(new URL(url));
}
Run Code Online (Sandbox Code Playgroud)

您还可以通过调用或用新对象setContentType替换来清除缓存。JTextPane这是因为缓存存储在JTextPane.