Javafx 如何序列化包含图像对象的映射?
我正在创建一个图像库,其中包含相册,每个相册都包含图片。这些IREM存储在如下的哈希映射中Javafx 如何序列化包含图像对象的映射?,javafx,serialization,Javafx,Serialization,我正在创建一个图像库,其中包含相册,每个相册都包含图片。这些IREM存储在如下的哈希映射中 HashMap<Album, ArrayList<Picture>> albums=new HashMap<>(); 我总是得到这个异常:java.io.NotSerializableException:javafx.scene.image.image 有没有办法使我的图片可以序列化?您需要自定义图片的序列化。要自定义对象的序列化,请使用以下两种方法: void r
HashMap<Album, ArrayList<Picture>> albums=new HashMap<>();
我总是得到这个异常:java.io.NotSerializableException:javafx.scene.image.image
有没有办法使我的图片可以序列化?您需要自定义
图片的序列化。要自定义对象的序列化,请使用以下两种方法:
void readObject(ObjectInputStream)抛出ClassNotFoundException、IOException
void writeObject(ObjectOutputStream)抛出IOException
这些方法可以有任何访问修饰符,但通常是(?)private
如果您有以下课程:
public class Picture implements Serializable {
private final String name;
private final String place;
private final String description;
private transient Image image;
public Picture(String name, String place, String description, Image image) {
this.name = name;
this.place = place;
this.description = description;
this.image = image;
}
public String getName() {
return name;
}
public String getPlace() {
return place;
}
public String getDescription() {
return description;
}
public Image getImage() {
return image;
}
}
关于图像的序列化,您至少有三个选项
序列化映像的位置
private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException {
in.defaultReadObject();
String url = (String) in.readObject();
if (url != null) {
image = new Image(url);
}
}
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObjet();
out.writeObject(image == null ? null : image.getUrl());
}
该方法是在JavaFX9中添加的
通过PixelReader
序列化图像的像素数据。反序列化时,您将使用PixelWriter
private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException {
in.defaultReadObject();
if (in.readBoolean()) {
int w = in.readInt();
int h = in.readInt();
byte[] b = new byte[w * h * 4];
in.readFully(b);
WritableImage wImage = new WritableImage(w, h);
wImage.getPixelWriter().setPixels(0, 0, w, h, PixelFormat.getByteBgraInstance(), b, 0, w * 4);
image = wImage;
}
}
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeBoolean(image != null);
if (image != null) {
int w = (int) image.getWidth();
int h = (int) image.getHeight();
byte[] b = new byte[w * h * 4];
image.getPixelReader().getPixels(0, 0, w, h, PixelFormat.getByteBgraInstance(), b, 0, w * 4);
out.writeInt(w);
out.writeInt(h);
out.write(b);
}
}
警告:以这种方式序列化像素数据将以未压缩格式保存图像。图像可能非常大,使用此方法时可能会给您带来问题
这取决于可用的PixelReader
,但情况并非总是如此。如果您阅读了的文档,您将看到(emphasis我的):
此方法返回一个PixelReader
,如果图像可读,则该方法提供读取图像像素的访问权限。如果此方法返回null,则此图像此时不支持读取。如果图像是从源加载的,并且仍然不完整,则此方法将返回null{如果您想将图像
保留为图片
的成员,则必须自定义序列化。您希望如何序列化图像
实际像素数据或图像的位置?我不知道确切的用例,但为什么要序列化图像?(假设您的意思是序列化像素数据。)如果直接进行,数据的大小将非常大,您将不得不执行大量IO。这就是为什么图像存储为PNG、JPEG等,因为您希望使用数据压缩。这也可以通过序列化来完成,但数据库中的blob不是更好的选择吗?@Slaw我需要序列化像素数据,每个图像都是loa由文件选择器编辑,然后由ImageView对象显示
private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException {
in.defaultReadObject();
if (in.readBoolean()) {
int w = in.readInt();
int h = in.readInt();
byte[] b = new byte[w * h * 4];
in.readFully(b);
WritableImage wImage = new WritableImage(w, h);
wImage.getPixelWriter().setPixels(0, 0, w, h, PixelFormat.getByteBgraInstance(), b, 0, w * 4);
image = wImage;
}
}
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeBoolean(image != null);
if (image != null) {
int w = (int) image.getWidth();
int h = (int) image.getHeight();
byte[] b = new byte[w * h * 4];
image.getPixelReader().getPixels(0, 0, w, h, PixelFormat.getByteBgraInstance(), b, 0, w * 4);
out.writeInt(w);
out.writeInt(h);
out.write(b);
}
}
private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException {
in.defaultReadObject();
if (in.readBoolean()) {
byte[] bytes = new byte[in.readInt()];
in.readFully(bytes);
image = new Image(new ByteArrayInputStream(bytes));
}
}
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeBoolean(image != null);
if (image != null) {
byte[] bytes;
try (InputStream is = new URL(image.getUrl()).openStream()) {
bytes = is.readAllBytes();
}
out.writeInt(bytes.length);
out.write(bytes);
}
}