在XMLJavaFX中存储图像

在XMLJavaFX中存储图像,xml,javafx,Xml,Javafx,我有一个类,我用XML保存它的数据,其中一个数据是默认情况下不能用XML保存的图像,当我读到时,我必须转换它,但我没有在图像类中找到任何parse()方法来解组它。是否可以将图像转换为字符串并将其转换回图像 谢谢我的“示例”项目中有这个示例。(我不知道我为什么要写它。)它基本上就像@jewelsea在他的评论中描述的那样 import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.i

我有一个类,我用XML保存它的数据,其中一个数据是默认情况下不能用XML保存的图像,当我读到时,我必须转换它,但我没有在图像类中找到任何
parse()
方法来解组它。是否可以将图像转换为字符串并将其转换回图像

谢谢

我的“示例”项目中有这个示例。(我不知道我为什么要写它。)它基本上就像@jewelsea在他的评论中描述的那样

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.PrintWriter;
import java.util.Base64;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

import javafx.embed.swing.SwingFXUtils;
import javafx.scene.image.Image;

import javax.imageio.ImageIO;
import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.XMLEvent;


public class ImageXMLAccessor {

    private final ExecutorService exec = Executors.newCachedThreadPool(r -> {
        Thread thread = new Thread(r);
        thread.setDaemon(true);
        return thread ;
    });

    public void saveImage(XMLEventWriter writer, XMLEventFactory eventFactory, Image image) 
            throws IOException, XMLStreamException {

        BufferedImage buffImage = SwingFXUtils.fromFXImage(image, null);
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        ImageIO.write(buffImage, "png", bytes);
        String encodedImage = Base64.getEncoder().encodeToString(bytes.toByteArray());
        writer.add(eventFactory.createCharacters(encodedImage));
    }

    public Image readImage(XMLEventReader eventReader) 
            throws IOException, XMLStreamException, InterruptedException, ExecutionException {

        PipedInputStream pipedInput = new PipedInputStream();

        FutureTask<Image> imageTask = new FutureTask<>(new Callable<Image>() {
            @Override
            public Image call() throws Exception {
                try (InputStream imageStream = Base64.getDecoder().wrap(pipedInput)) {

                    BufferedImage buffImage = ImageIO.read(imageStream);
                    return SwingFXUtils.toFXImage(buffImage, null);
                }
            }
        });

        exec.submit(imageTask);

        try (PrintWriter output = new PrintWriter(new PipedOutputStream(pipedInput))) {
            for (boolean done = false ; eventReader.hasNext() && ! done; ) {
                XMLEvent event = eventReader.nextEvent();
                if (event.isCharacters()) {
                    Characters characters = event.asCharacters();
                    String data = characters.getData();
                    output.write(data);
                } else if (event.isEndElement()) {
                    output.close();
                    done = true ;
                }
            }
        } 

        return imageTask.get();
    }

}
导入java.awt.image.buffereImage;
导入java.io.ByteArrayOutputStream;
导入java.io.IOException;
导入java.io.InputStream;
导入java.io.PipedInputStream;
导入java.io.PipedOutputStream;
导入java.io.PrintWriter;
导入java.util.Base64;
导入java.util.concurrent.Callable;
导入java.util.concurrent.ExecutionException;
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
导入java.util.concurrent.FutureTask;
导入javafx.embed.swing.SwingFXUtils;
导入javafx.scene.image.image;
导入javax.imageio.imageio;
导入javax.xml.stream.XMLEventFactory;
导入javax.xml.stream.XMLEventReader;
导入javax.xml.stream.XMLEventWriter;
导入javax.xml.stream.XMLStreamException;
导入javax.xml.stream.events.Characters;
导入javax.xml.stream.events.XMLEvent;
公共类ImageXMLAccessor{
private final ExecutorService exec=Executors.newCachedThreadPool(r->{
螺纹=新螺纹(r);
setDaemon(true);
返回线程;
});
public void saveImage(XMLEventWriter编写器、XMLEventFactory eventFactory、图像图像)
抛出IOException、XMLStreamException{
buffereImage buffImage=SwingFXUtils.fromFXImage(image,null);
ByteArrayOutputStream字节=新建ByteArrayOutputStream();
写入(buffImage,“png”,字节);
字符串encodedImage=Base64.getEncoder().encodeToString(bytes.toByteArray());
add(eventFactory.createCharacters(encodedImage));
}
公共映像读取映像(XMLEventReader-eventReader)
抛出IOException、XMLStreamException、InterruptedException、ExecutionException{
PipedInputStream pipedInput=新的PipedInputStream();
FutureTask imageTask=新的FutureTask(新的可调用(){
@凌驾
公共映像调用()引发异常{
尝试(InputStream imageStream=Base64.getDecoder().wrap(pipedInput)){
BuffereImage buffImage=ImageIO.read(imageStream);
返回SwingFXUtils.toFXImage(buffImage,null);
}
}
});
执行提交(图像任务);
try(PrintWriter输出=新的PrintWriter(新的PipedOutputStream(pipedInput))){
for(boolean done=false;eventReader.hasNext()&&!done;){
XMLEvent=eventReader.nextEvent();
if(event.isCharacters()){
Characters=event.asCharacters();
字符串数据=个字符。getData();
输出。写入(数据);
}else if(event.isEndElement()){
output.close();
完成=正确;
}
}
} 
返回imageTask.get();
}
}
这是一个使用它的测试程序。可以打开JPG或PNG文件,然后将其另存为XML(或打开结构类似的XML文件):

导入java.io.File;
导入java.io.IOException;
导入java.io.Writer;
导入java.nio.file.Files;
导入javafx.application.application;
导入javafx.application.Platform;
导入javafx.beans.property.ObjectProperty;
导入javafx.beans.property.SimpleObject属性;
导入javafx.geometry.Insets;
导入javafx.geometry.Pos;
导入javafx.scene.scene;
导入javafx.scene.control.Button;
导入javafx.scene.image.image;
导入javafx.scene.image.ImageView;
导入javafx.scene.layout.BorderPane;
导入javafx.scene.layout.HBox;
导入javafx.stage.FileChooser;
导入javafx.stage.FileChooser.ExtensionFilter;
导入javafx.stage.stage;
导入javax.xml.namespace.QName;
导入javax.xml.stream.FactoryConfigurationError;
导入javax.xml.stream.XMLEventFactory;
导入javax.xml.stream.XMLEventReader;
导入javax.xml.stream.XMLEventWriter;
导入javax.xml.stream.XMLInputFactory;
导入javax.xml.stream.XMLOutputFactory;
导入javax.xml.stream.XMLStreamException;
导入javax.xml.stream.events.StartElement;
导入javax.xml.stream.events.XMLEvent;
公共类ImageXMLTest扩展了应用程序{
@凌驾
公共无效开始(阶段primaryStage){
ImageXMLAccessor accessor=新的ImageXMLAccessor();
FileChooser chooser=新建FileChooser();
chooser.getExtensionFilters().add(新的ExtensionFilter(“图像文件”,“*.jpg”,“*.jpg”,“*.png”,“*.png”));
添加(新的ExtensionFilter(“XML文件”、“*.XML”、“*.XML”));
按钮打开按钮=新按钮(“打开…”);
ObjectProperty currentImage=新的SimpleObject属性();
openButton.setOnAction(事件->{
File imageFile=chooser.showOpenDialog(primaryStage);
if(imageFile!=null){
if(imageFile.toString().toLowerCase().endsWith(“.xml”)){
openFromXMLFile(imageFile、currentImage、访问器);
}否则{
openFromImageFile(imageFile,currentImage);
}
}
});
Button saveButton=新建按钮(“保存到XML…”);
saveButton.setOnAction(事件->{
File xmlFile=chooser.showsavedilog(primaryStage);
如果(xmlFile!=null){
试一试{
saveImageToXML(存取器,currentImage,xmlFile);
}捕获(例外e){
e、 printStackTrace();
}
}
});
saveButton.disableProperty().bind(currentImage.isNull());
import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.nio.file.Files;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;
import javafx.stage.Stage;

import javax.xml.namespace.QName;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

public class ImageXMLTest extends Application {

    @Override
    public void start(Stage primaryStage) {
        ImageXMLAccessor accessor = new ImageXMLAccessor();
        FileChooser chooser = new FileChooser();
        chooser.getExtensionFilters().add(new ExtensionFilter("Image Files", "*.jpg", "*.JPG", "*.png", "*.PNG"));
        chooser.getExtensionFilters().add(new ExtensionFilter("XML files", "*.xml", "*.XML"));
        Button openButton = new Button("Open...");
        ObjectProperty<Image> currentImage = new SimpleObjectProperty<>();
        openButton.setOnAction(event -> {
            File imageFile = chooser.showOpenDialog(primaryStage);
            if (imageFile != null) {
                if (imageFile.toString().toLowerCase().endsWith(".xml")) {
                    openFromXMLFile(imageFile, currentImage, accessor);
                } else {
                    openFromImageFile(imageFile, currentImage);                 
                }
            }
        });
        Button saveButton = new Button("Save to XML...");
        saveButton.setOnAction(event -> {
            File xmlFile = chooser.showSaveDialog(primaryStage);
            if (xmlFile != null) {
                try {
                    saveImageToXML(accessor, currentImage, xmlFile);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        saveButton.disableProperty().bind(currentImage.isNull());
        HBox controls = new HBox(5, openButton, saveButton);
        controls.setPadding(new Insets(10));
        controls.setAlignment(Pos.CENTER);
        ImageView imageView = new ImageView();
        imageView.setFitHeight(600);
        imageView.setFitWidth(800);
        imageView.setPreserveRatio(true);
        imageView.imageProperty().bind(currentImage);
        BorderPane root = new BorderPane(imageView, null, null, controls, null);
        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private void saveImageToXML(ImageXMLAccessor accessor,
            ObjectProperty<Image> currentImage, File xmlFile)
            throws IOException, FactoryConfigurationError, XMLStreamException {
        Writer writer = Files.newBufferedWriter(xmlFile.toPath());
        XMLEventFactory eventFactory = XMLEventFactory.newFactory();
        XMLEventWriter eventWriter = XMLOutputFactory.newFactory().createXMLEventWriter(writer);
        eventWriter.add(eventFactory.createStartDocument());
        QName imageElement = new QName("image");
        eventWriter.add(eventFactory.createStartElement(imageElement, null, null));
        accessor.saveImage(eventWriter, eventFactory, currentImage.get());
        eventWriter.add(eventFactory.createEndElement(imageElement, null));
        eventWriter.add(eventFactory.createEndDocument());
        writer.close();
    }

    private void openFromImageFile(File imageFile,
            ObjectProperty<Image> currentImage) {
        try {
            currentImage.set(new Image(imageFile.toURI().toURL().toExternalForm(), true));
        } catch (Exception exc) {
            exc.printStackTrace();
        }
    }



    public void openFromXMLFile(File xmlFile, ObjectProperty<Image> currentImage, ImageXMLAccessor accessor) {

        new Thread(() -> {
            XMLInputFactory inputFactory = XMLInputFactory.newFactory() ;
            XMLEventReader eventReader = null ;
            try {
                eventReader = inputFactory.createXMLEventReader(Files.newBufferedReader(xmlFile.toPath()));
                while (eventReader.hasNext()) {
                    XMLEvent event = eventReader.nextEvent();
                    if (event.isStartElement()) {
                        StartElement startEl = event.asStartElement();
                        if ("image".equals(startEl.getName().getLocalPart())) {
                            Image image;
                            try {
                                image = accessor.readImage(eventReader);
                                Platform.runLater(() -> currentImage.set(image));
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (eventReader != null ){
                    try {
                        eventReader.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

    }

    public static void main(String[] args) {
        launch(args);
    }
}