java - 显示 base64 编码的图像

标签 java html jtextpane

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

<html>
  <head>
    <style type="text/css">
    </style>
  </head>
  <body>
  </body>
</html>

我插入文本:

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

以这种方式插入的所有文本都可以正确显示,但是当我尝试插入一个 base64 编码的图像时:

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

我只有一个占位符图像。当尝试使用正常的源路径时,它起作用了。然而,在线获取 base64 代码并使用它也让我得到了一个占位符图像,而完全相同的代码也适用于 w3school.com 的 HTML tryit 编辑器。

最佳答案

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

事实证明,我们可以手动将图片添加到图片缓存中。这可用于选择一些其他无效的 url 并为其分配图像。


让我们将图像添加到缓存中并在 JTextPane 中显示它!

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

byte[] imgBytes = decodeBase64(base64Code);
BufferedImage img = ImageIO.read(new ByteArrayInputStream(imgBytes));

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


现在我们有了图像 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;
}

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

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

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


我们现在可以将它与 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);

请注意,您必须调用 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));
}

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

关于java - 显示 base64 编码的图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53712428/

相关文章:

java - JTextPane插入组件,垂直对齐错误

Java DES 加密、C# DES 解密

java - 使用计时器打破循环

java - RabbitMQ 使用 Spring 直接回复的问题

html - 知道 firefox 中何时发生预取

javascript - 打印区域中的 CSS

java - webelement element=driver.findelement(By.id ("")) 中的 driver.findelementby(By.id ("")) 是什么

javascript - 关闭灯箱后模态窗口覆盖仍然存在

Java JTextPane StyleConstants 对齐无法正常工作

java - JTextPane 中的监听器