我有一个类,我使用XML来保存其数据,其中一个数据是默认情况下无法保存在XML中的图像,正如我读here,我必须转换它,但我没有在图像类中找不到任何parse()
方法来解组它。是否可以将图像转换为字符串并将其转换回图像?
由于
答案 0 :(得分:2)
我的“示例”项目中有这个例子。 (我不知道为什么要写它。)它基本上可以像@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();
}
}
这是一个使用它的测试程序。您可以打开JPG或PNG文件,然后将其另存为XML(或打开类似结构的XML文件):
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);
}
}