显示 base64 编码的图像
Display base64-encoded image
我在 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
. This can be done using the ImageIO
class.
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)
如果不是有效的 url.
可能会抛出 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);
请注意,在将图像添加到缓存之前必须调用 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
.
中
我在 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
. This can be done using the ImageIO
class.
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)
如果不是有效的 url.
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);
请注意,在将图像添加到缓存之前必须调用 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
.