Je peux voir beaucoup de réponses, ne répondant pas vraiment aux trois questions du PO.
1) Un mot sur les performances: les tableaux d'octets sont probablement inefficaces, sauf si vous pouvez utiliser un ordre d'octets de pixels exact qui correspond à la résolution actuelle et à la profondeur de couleur de vos cartes graphiques.
Pour obtenir les meilleures performances de dessin, il vous suffit de convertir votre image en une BufferedImage qui est générée avec un type correspondant à votre configuration graphique actuelle. Voir createCompatibleImage sur https://docs.oracle.com/javase/tutorial/2d/images/drawonimage.html
Ces images seront automatiquement mises en cache sur la mémoire de la carte graphique après avoir dessiné plusieurs fois sans aucun effort de programmation (ceci est standard dans Swing depuis Java 6), et donc le dessin réel prendra un temps négligeable - si vous n'avez pas changé l'image .
La modification de l'image entraînera un transfert de mémoire supplémentaire entre la mémoire principale et la mémoire GPU - ce qui est lent. Évitez de "redessiner" l'image en une BufferedImage, évitez donc de faire getPixel et setPixel par tous les moyens.
Par exemple, si vous développez un jeu, au lieu de dessiner tous les acteurs du jeu sur une BufferedImage puis sur un JPanel, il est beaucoup plus rapide de charger tous les acteurs sous forme de BufferedImages plus petits et de les dessiner un par un dans votre code JPanel à leur position correcte - de cette façon, il n'y a pas de transfert de données supplémentaires entre la mémoire principale et la mémoire GPU, à l'exception du transfert initial des images pour la mise en cache.
ImageIcon utilisera une BufferedImage sous le capot - mais en gros, allouer une BufferedImage avec le bon mode graphique est la clé, et il n'y a aucun effort pour le faire correctement.
2) La manière habituelle de procéder est de dessiner une BufferedImage dans une méthode paintComponent surchargée de JPanel. Bien que Java prenne en charge une grande quantité de fonctionnalités supplémentaires telles que les chaînes de tampons contrôlant les images volatiles mises en cache dans la mémoire du GPU, il n'est pas nécessaire d'utiliser ces éléments depuis Java 6 qui fait un travail raisonnablement bon sans exposer tous ces détails de l'accélération du GPU.
Notez que l'accélération GPU peut ne pas fonctionner pour certaines opérations, telles que l'étirement d'images translucides.
3) N'ajoutez pas. Il suffit de le peindre comme mentionné ci-dessus:
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
"Ajouter" est logique si l'image fait partie de la mise en page. Si vous en avez besoin en tant qu'image d'arrière-plan ou de premier plan remplissant le JPanel, dessinez simplement paintComponent. Si vous préférez brasser un composant Swing générique qui peut montrer votre image, il est alors la même histoire (vous pouvez utiliser un JComponent et remplacer la méthode de paintComponent) - puis ajoutez ce à votre disposition des composants GUI.
4) Comment convertir le tableau en une image tampon
La conversion de vos tableaux d'octets en PNG, puis leur chargement nécessitent beaucoup de ressources. Une meilleure façon est de convertir votre tableau d'octets existant en BufferedImage.
Pour cela: ne pas utiliser pour les boucles et copier les pixels. C'est très très lent. Au lieu:
- apprendre la structure d'octets préférée de la BufferedImage (de nos jours, il est sûr de supposer RVB ou RGBA, qui est de 4 octets par pixel)
- apprendre la ligne de numérisation et la taille de numérisation en cours d'utilisation (par exemple, vous pourriez avoir une image de 142 pixels de large - mais dans la vraie vie qui sera stockée sous forme de tableau d'octets de 256 pixels de large car il est plus rapide de traiter cela et de masquer les pixels inutilisés par le matériel GPU )
- puis, une fois que vous avez construit un tableau selon ces principes, la méthode du tableau setRGB du BufferedImage peut copier votre tableau sur le BufferedImage.
MemoryImageSource
que de les convertir au format JPEG ou PNG, puis de les lireImageIO
comme le suggèrent la plupart des réponses. Vous pouvez obtenir un àImage
partir d'unMemoryImageSource
construit avec vos données d'image en utilisantcreateImage
et afficher comme suggéré dans l'une des réponses.