提问人:Maxim 提问时间:11/17/2023 最后编辑:Maxim 更新时间:11/18/2023 访问量:61
在 JavaFX 中将剪贴板中的图像编码为 base64
Encode an image from the clipboard as base64 in JavaFX
问:
我有一个 JavaFX 应用程序,我试图从剪贴板读取图像并将其编码为 base64 字符串以将其保存在数据库中(最大 100x100 像素的小屏幕截图)。有几个示例可以将图像文件读取为字节数组,但我找不到获取剪贴板图像字节的方法。我试过这个:
var image = Clipboard.getSystemClipboard().getImage();
if(image != null) {
int w = (int)image.getWidth();
int h = (int)image.getHeight();
byte[] buf = new byte[w * h * 4];
image.getPixelReader().getPixels(0, 0, w, h, PixelFormat.getByteBgraInstance(), buf, 0, w * 4);
return Base64.getEncoder().encodeToString(buf);
}
return null;
但是我从中获得的字符串内容无法以任何格式解码(使用多个在线工具)。
答:
3赞
Slaw
11/17/2023
#1
从调用中获取的字节只是原始颜色/像素数据。它不是像 PNG 或 JPEG 这样的图像文件格式。如果您希望其他软件能够解码 Base64 编码的图像,则必须首先将像素编码为实际的图像文件格式。例如:getPixels
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UncheckedIOException;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.image.Image;
import javax.imageio.ImageIO;
public final class ImageUtils {
private ImageUtils() {}
public static byte[] toImageFile(Image image, String format) {
var out = new ByteArrayOutputStream();
try {
ImageIO.write(SwingFXUtils.fromFXImage(image, null), format, out);
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
return out.toByteArray();
}
}
注意:SwingFXUtils
来自 javafx.swing
模块。
一旦你有了图像文件,那么你可以对字节进行 Base64 编码:
var image = Clipboard.getSystemClipboard().getImage();
var bytes = ImageUtils.toImageFile(image, "png");
var base64Str = Base64.getEncoder().encodeToString(bytes);
注意:PNG 是一种无损格式。如果您想要较小的图像文件,则可以使用JPEG等有损格式。
但是你提到将这个图像保存到数据库中。如果您要这样做,那么我建议您只将图像存储为 blob。例如,如果您直接使用 JDBC:
var image = Clipboard.getSystemClipboard().getImage();
var bytes = ImageUtils.toImageFile(image, "png");
try (var conn = DriverManager.getConnection("...")) {
try (var stat = conn.prepareStatement("INSERT INTO Foo (image) VALUES (?)")) {
stat.setBinaryStream(1, new ByteArrayInputStream(bytes));
stat.executeUpdate();
}
}
如果需要,您当然可以继续对代码的其他部分使用 Base64 编码。
评论
0赞
Maxim
11/17/2023
好的,但我收到此错误:java.lang.ClassNotFoundException: javafx.embed.swing.SwingFXUtils,尽管它在 IDE 中被识别。我还没有使用module-info文件,我必须在那里放一些东西吗?
1赞
jewelsea
11/18/2023
@Maxim 如果您没有 module-info 文件,则您的代码不是模块化的。javafx.swing 是一个模块,即使您的代码不是模块化的,它也需要位于模块路径上。有关为各种 IDE 和 gradle 设置非模块化项目的信息(您在另一条评论中提到过)openjfx.io。这显示了如何将其他 JavaFX 模块(如 javafx.controls)放在模块路径上并使用它们。javafx.swing 模块在设置中没有什么不同,但您确实需要进行设置并为所需模块使用正确的模块名称和路径
评论
SwingFXUtils
Image
BufferedImage
ImageIO