JavaFX2 WebView et images en mémoire


Voici le problème: j'ai plusieurs images et je voudrais les utiliser lors de l'affichage d'un code HTML dans Javafx's WebView.

L'implémentation actuelle est très évidente: il y a un fichier, qui est lié au contenu HTML. Je suppose que WebView ne régresse pas de JEditorPane et ne fera qu'une seule opération d'E/S même si l'image est référencée 10 000 fois dans tout le contenu.

Cependant, ce serait génial d'avoir une seule instance Image et de la nourrir dans WebView quand elle rencontre la balise <img> pertinente.

J'ai vu qu'il existe une excellente demi-solution impliquant URL la gestion, mais le problème demeure: vous avez une instance Image que vous convertissez en un format de stockage (BMP, PNG avec des extensions propriétaires, etc.) et gardez cela en mémoire. Cependant, cela signifie que chaque fois que WebView désire une résolution d'image, il doit ensuite analyser manuellement l'image à partir de données binaires. En fin de compte, vous avez juste un fichier mappé à la mémoire plus une instance interne Image à la place d'une instance partagée Image.

Avec JEditorPane, vous pouvez pousser Image s dans son cache d'image et vous débarrasser de ces problèmes. Malheureusement, depuis Java 7, ce composant est inutilisable et hors de question.

, Fondamentalement, est-il une chance WebView/WebEngine maintient un cache/équivalent et est-il possible de pré-remplir?

Author: afk5min, 2014-04-10

1 answers

    /**
     * Encodes the image as a whole into PNG, then into Base64 and finally into an URI suitable for the HTML {@code <img>} tag.
     * 
     * @param image an image
     * @return image as URI (image within the URI)
     * @throws IIOException if there is a fault with an image writer
     * @throws IOException in case of a general I/O error
     */
    public static final String getImageSrcForWebEngine(RenderedImage image) throws IIOException, IOException
    {
        final ByteArrayOutputStream output = new ByteArrayOutputStream();
        ImageIO.write(image, "PNG", output);
        return "data:base64," + Base64.getMimeEncoder().encodeToString(output.toByteArray());
    }

Exemple d'utilisation:

RenderedImage image = […];
String tag = "<img src=\"" + getImageSrcForWebEngine(image) + "\" border=\"0\" />";

SSCCE:

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Base64;

import javax.imageio.IIOException;
import javax.imageio.ImageIO;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.web.WebView;
import javafx.stage.Stage;

public class WebViewWithMemoryImages extends Application
{
    private static String IMAGE_IN_MEMORY;

    @Override
    public void start(Stage primaryStage)
    {
        WebView webView = new WebView();
        webView.getEngine().loadContent("<html><body><img src=\"" + IMAGE_IN_MEMORY + "\"></body></html>");
        primaryStage.setScene(new Scene(webView, 420, 420));
        primaryStage.show();
    }

    public static void main(String[] args) throws Exception
    {
        BufferedImage image = new BufferedImage(400, 400, BufferedImage.TYPE_INT_BGR);
        Graphics2D g = image.createGraphics();
        try
        {
            g.setColor(Color.RED);
            g.fillRect(0, 0, 400, 400);
            g.setColor(Color.WHITE);
            g.fillRect(50, 50, 300, 300);
            g.setColor(Color.BLACK);
            g.fillRect(100, 100, 200, 200);
            g.drawString("No image files were used in this WebView.", 90, 70);
        }
        finally
        {
            g.dispose();
        }
        IMAGE_IN_MEMORY = getImageSrcForWebEngine(image);

        launch(args);
    }

    public static String getImageSrcForWebEngine(RenderedImage image) throws IIOException, IOException
    {
        final ByteArrayOutputStream output = new ByteArrayOutputStream();
        ImageIO.write(image, "PNG", output);
        return "data:base64," + Base64.getMimeEncoder().encodeToString(output.toByteArray());
    }
}
 2
Author: afk5min, 2016-05-13 17:22:38