Receive png from XML file using JavaFX

349 Views Asked by At

I have a class named Person. Each Person has an avatar image stored as javafx.scene.image.Image field. I am trying to write those images from a collection of Persons to an xml file.

This is how i write the image:

Image image = p.getImage();
BufferedImage img = SwingFXUtils.fromFXImage(image, null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(img, "png", baos);
// baos.flush();
String encodedImage = Base64.getEncoder().encodeToString(baos.toByteArray());
baos.close();
xmlEventWriter.add(xmlEventFactory.createCharacters(encodedImage));

And this is how i am trying to read it:

byte[] bytes = Base64.getDecoder().decode(event.asCharacters().getData());
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
BufferedImage image = ImageIO.read(byteArrayInputStream);
personImage = SwingFXUtils.toFXImage(image, null);

Problem begins when reading encoded image from xml file. I am not receiving the whole set of characters. Value of event.asCharacters().getData() is only a part of what can be found in the xml file.

That is why i receive a javax.imageio.IIOException: Error reading PNG image data @ (PersonXMLTool.java:77) which is BufferedImage image = ImageIO.read(byteArrayInputStream); and a Caused by: java.io.EOFException: Unexpected end of ZLIB input stream.

At first i was using apache commons Base64 but it does not make any difference. On my test project i was doing the same and it worked. The difference was i did not write the encoded image to any xml file but used the String it generated for me.

Any help appreciated.

1

There are 1 best solutions below

0
James_D On BEST ANSWER

It looks like you are assuming the character data is all transmitted in a single XMLEvent. This won't be the case (unless the image is tiny): typically you will receive the character data in multiple events.

So you need to parse the xml file using something like this:

            XMLInputFactory inputFactory = XMLInputFactory.newFactory() ;
            XMLEventReader eventReader = inputFactory.createXMLEventReader(Files.newBufferedReader(xmlFile.toPath()));
            StringBuilder encodedImageBuffer = new StringBuilder();

            boolean readingImage = false ;

            while (eventReader.hasNext() && encodedImage == null) {
                XMLEvent event = eventReader.nextEvent();
                if (event.isStartElement()) {
                    StartElement el = event.asStartElement();
                    if ("image".equals(el.getName().getLocalPart())) {
                        readingImage = true ;
                    }
                }
                if (event.isCharacters() && readingImage) {
                    Characters characters = event.asCharacters();
                    encodedImageBuffer.append(characters.getData());
                }
                if (event.isEndElement()) {
                    EndElement el = event.asEndElement();
                    if ("image".equals(el.getName().getLocalPart())) {
                        String encodedImage = encodedImageBuffer.toString();
                        byte[] imageData = Base64.getDecoder().decode(encodedImage);
                        ByteArrayInputStream dataInputStream = new ByteArrayInputStream(imageData);
                        BufferedImage buffImage = ImageIO.read(dataInputStream);
                        Image image = SwingFXUtils.toFXImage(buffImage, null);
                    }
                }
            }