Enregistrement d'un JPanel au format bitmap

Signaler
Messages postés
28
Date d'inscription
mercredi 23 juin 2004
Statut
Membre
Dernière intervention
9 juillet 2004
-
Messages postés
333
Date d'inscription
dimanche 25 mai 2003
Statut
Membre
Dernière intervention
23 novembre 2009
-
Bonjour
Je voudrais savoir si quelqu'un aurait pas déjà eu à convertir l'image affichée sur un Panel en format bitmap pour ensuite l'enregistrer sur le dur.
Ce qui me pose problème, c'est surtout le coté conversion JPanel ->Bitmap

23 réponses

Messages postés
333
Date d'inscription
dimanche 25 mai 2003
Statut
Membre
Dernière intervention
23 novembre 2009
1
look at my source !!
Filtres pour image
dans la classe Enregistrement

tu fais une BufferedImage de la taille du panel
BufferedImage im = new BufferedImage(w, h);

tu dessines le jpanel dedans
jPanel.paintComponent(im.getGraphics());
(ou qqchose qui ressemble à ca)

et tu enregistres comme dans ma classe

A+
Dobeliou
[Il ne faut jamais jouer à saute-mouton avec une licorne]
Messages postés
28
Date d'inscription
mercredi 23 juin 2004
Statut
Membre
Dernière intervention
9 juillet 2004
5
Dobel, tu es mon nouveau héros. Je te remercie pour ton aide précieuse. Je suis allé voir tes sources et c'est exactement ce qu'il me fallait. Tu m'as fait économisé plusieurs heures de travail et quand on sait à quel point je suis à la bourre dans mon projet, c'est pas négligeable.

Tu aurais pas des long cheveux noirs, une couronne d'épines sur la tête, et une étonnante facilité à marcher sur l'eau?
Messages postés
333
Date d'inscription
dimanche 25 mai 2003
Statut
Membre
Dernière intervention
23 novembre 2009
1
c'est sympa :big)

Dobeliou
[Il ne faut jamais jouer à saute-mouton avec une licorne]
Messages postés
333
Date d'inscription
dimanche 25 mai 2003
Statut
Membre
Dernière intervention
23 novembre 2009
1
Salut

j'avais pas lu ton message précédant au sujet du jpeg sans utiliser ImageIO (suivi d'une conversation fort passionnante :big) )

dans ma source, pour le truc :
DataOutputStream sortie = new DataOutputStream(new FileOutputStream(fichier));
JPEGImageEncoder enc = JPEGCodec.createJPEGEncoder(sortie);
JPEGEncodeParam param = enc.getDefaultJPEGEncodeParam(image);
param.setQuality(1f, false);
enc.setJPEGEncodeParam(param);
enc.encode(image);
sortie.close();

les classes JPEGEncodeParam etc.. ne sont peut-être pas dans le package javax.imageio (elles sont dans com.sun.image.codec....)
mais ce sont en fait les codecs utilisés par ImageIO

donc les utiliser, c'est un peu comme utiliser ImageIO...

en fait, j'avais écrit ca à la place de
ImageIO.write(image, "jpg", fichier)
uniquement pour pouvoir regler la qualité

(c'est quand même bizare comme contrainte de pas pouvoir utiliser ImageIO...)

A+
Dobeliou
[Il ne faut jamais jouer à saute-mouton avec une licorne]
Messages postés
28
Date d'inscription
mercredi 23 juin 2004
Statut
Membre
Dernière intervention
9 juillet 2004
5
Voilà, apparement, j'ai toujours un problème sur ma conversion en Bitmap. Voici mon code :

public void GraphicsToBitmap()
{
BufferedImage image = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_BYTE_INDEXED);
File fichier = new File("Resultats/ImageBitmapCarteOpt.bmp");
this.paint(image.getGraphics());
try{
ImageIO.write(image, "bmp",fichier);
}
catch (IOException IOE){
IOE.printStackTrace();
}
}

Il créer bien le fichier en question mais ce n'est pas l'image du Graphics qui est enregistrée.
En fait, l'image ne comporte aucune donnée.

Je ne comprend pas pourquoi ca refuse de marcher.
Au fait, j'ai bien droit d'utiliser ImageIO. En fait, sur l'ordinateur que j'utilisais, il n'avait pas une version de la plateforme API suffisament récente je crois.

Merci pour votre aide
Messages postés
333
Date d'inscription
dimanche 25 mai 2003
Statut
Membre
Dernière intervention
23 novembre 2009
1
c'est bizare, j'ai essayé chez moi en mettant ta méthode dans un JPanel et ca marche très bien

où appelles-tu ta méthode GraphicsToBitmap() ?

Dobeliou
[Il ne faut jamais jouer à saute-mouton avec une licorne]
Messages postés
28
Date d'inscription
mercredi 23 juin 2004
Statut
Membre
Dernière intervention
9 juillet 2004
5
Ma méthode GraphicsToBitmap est appelée dans la classe principale suite à l'appui sur un bouton. Ce que je ne comprend pas, c'est que j'ai aussi une méthode GraphicsToJpeg juste au dessus de la méthode GraphicsToBitmap. Les deux sont appelées au même endroit simultanément.
Pourtant, la conversion en bitmap ne crée rien d'autre qu'une image vide.
L'erreur provient donc forcément du code que j'ai affiché plus haut.
Quand tu as fait ton test, l'image générée n'était pas vide aussi?

CONCLUSION :
C'est parfois mystérieux le java.
Messages postés
333
Date d'inscription
dimanche 25 mai 2003
Statut
Membre
Dernière intervention
23 novembre 2009
1
je viens de constater que j'avais utiliser une béta du jdk 1.5.0
en effet, avec le 1.4, ca marche pas

en verifiant les differents formats acceptés :
String[] s = ImageIO.getWriterMIMETypes();
for (int i=0; i<s.length; i++) {
System.out.println(s[i]);
}

il semble que le bmp ne soit pas supprté par la 1.4

tu peux toujours utiliser le code que j'avais mis en commentaire dans ma source
mais l'enregistrement sera plus lent (et se sera pas du 256 couleurs comme avec l'utilisation de BufferedImage.TYPE_BYTE_INDEXED)

Salut
Dobeliou
[Il ne faut jamais jouer à saute-mouton avec une licorne]
Messages postés
28
Date d'inscription
mercredi 23 juin 2004
Statut
Membre
Dernière intervention
9 juillet 2004
5
Merci pour ton aide.
Effectivement, je travaille avec la jdk 1.4.
Pour l'autre code dont tu parles, il doit s'agir de ton enregistrement manuel je suppose.
Je vais essayer de voir si ça fonctionne.
Je m'y attèle tout de suite.
Messages postés
28
Date d'inscription
mercredi 23 juin 2004
Statut
Membre
Dernière intervention
9 juillet 2004
5
Ca marche bien!!!
Excellent.
merci beaucoup pour ton aide.
Je te poserais bien une dernière question. J'ai besoin de récupérer la couleur d'un point à un endroit précis x et y du panel pour y appliquer manuellement les algos d'érosion et de dilatation.
Tu sais pas comment faire pour récupérer la couleur d'un panel à un endroit précis.
(petite précision, l'image est une image binaire).
Merci d'avance.
Messages postés
333
Date d'inscription
dimanche 25 mai 2003
Statut
Membre
Dernière intervention
23 novembre 2009
1
la seule méthode que je connaise, c'est encore en passant par une BufferedImage
tu fais une BufferedImage de type TYPE_BYTE_BINARY (pour le noir et blanc)
tu dessines ton JPanel dedans de la même façon que précédemment
this.paint(image.getGraphics());

tu disposes des méthodes getRGB sur l'image
les valeurs retournées contiennent la couche alpha et sont au format ARGB
donc tu as ff000000 pour du noir et ffffffff pour du blanc

voilà !

Salut
Dobeliou
[Il ne faut jamais jouer à saute-mouton avec une licorne]
Messages postés
28
Date d'inscription
mercredi 23 juin 2004
Statut
Membre
Dernière intervention
9 juillet 2004
5
Excellent!!!
Tout marche.
J'arrive à faire mon érosion et ma dilatation, et mes conversion Bitmap et JPEG marchent parfaitement.
Il me reste un autre petit problème que je traine depuis longtemps.
Je dois à un certain moment de mon code voir avec précision si une ellipse2D intersects une ligne2D. Cette ligne2D peut avoir n'importe quel coefficient directeur.
Comme il m'a semblé ne pas y avoir de méthode prédéfinie dans le tutorial, et comme la position de l'ellipse est son coin supérieur gauche, j'ai fait petit calcul de base pour récupérer les coordonnées de son centre.
Ensuite, vu que je connais diamètre du cercle (car c'est une ellipse de grand axe et de petit axe égaux), j'ai fait une méthode qui renvoie true si la plus courte distance de la ligne au centre du cercle est inférieure au diamètre et false sinon.
Seulement cette méthode n'est pas très précise et il arrive que l'intersection existe et que je ne le vois pas.

Connais tu une méthode pour avoir avec précision la certitude qu'une ellipse2D et une ligne2D s'intersects?
Messages postés
28
Date d'inscription
mercredi 23 juin 2004
Statut
Membre
Dernière intervention
9 juillet 2004
5
Voici mon code:

public boolean IntersectsPoteau(Line2D Ligne)
{

int i, TailleMax = PoteauListe.size();
Ellipse2D poteau2;
double absHautGauche; // Coordonnées du point en haut à gauche de l'ellipse
double ordHautGauche;
double absCentre;
double ordCentre;

boolean Intersection = false;
i = 0;
for (i = 0; i < TailleMax; i++)
{
poteau2 = (Ellipse2D)PoteauListe.elementAt(i);
absHautGauche = poteau2.getX();
ordHautGauche = poteau2.getY();
absCentre = absHautGauche + (TaillePoteau/2)*Math.sin(45);
ordCentre = ordHautGauche + (TaillePoteau/2)*Math.cos(45);
if ( Ligne.ptSegDist(absCentre, ordCentre) < TaillePoteau/2)
{
Intersection = true;
}
}
return Intersection;


}

Tu aurais pas une petite idée pour l'améliorer ou pour utiliser méthode plus précise?
En tout cas, merci pour ton aide. Je suis en avance sur mes objectifs de stage grace à toi.
Messages postés
333
Date d'inscription
dimanche 25 mai 2003
Statut
Membre
Dernière intervention
23 novembre 2009
1
il n'y a rien a redire sur ton code ;-p

juste verifier que TaillePoteau est bien 1 double (sinon, la division par 2 retourne aussi un int...)

j'essayerais bien, pour être sur d'avoir les mêmes résultats que le dessin, de convertir en int les coordonnées du centre dans le test :
if ( Ligne.ptSegDist((int) absCentre, (int) ordCentre) < TaillePoteau/2)

Dobeliou
[Il ne faut jamais jouer à saute-mouton avec une licorne]
Messages postés
28
Date d'inscription
mercredi 23 juin 2004
Statut
Membre
Dernière intervention
9 juillet 2004
5
TaillePoteau est bien un double.
J'ai fait le forçage de type sur les coordonnées du centre du cercle.
Mais apparement, ça ne résoud pas le problème de détection.
Perso, je trouve ça vraiment bizarre.
J'ai passé du temps à essayer de comprendre pourquoi il détecte mal l'intersection mais, comme j'ai pas trop l'intuition divine du java pour l'instant, je bloque.
En plus, c'est une méthode toute simple donc elle devrait marcher.
Messages postés
333
Date d'inscription
dimanche 25 mai 2003
Statut
Membre
Dernière intervention
23 novembre 2009
1
ah si!!!
il y a bien une gaffe !

si TaillePoteau designe le diametre, alors tu as
absCentre = absHautGauche + (TaillePoteau/2);
ordCentre = ordHautGauche + (TaillePoteau/2);

sinon, c'est qu'il désigne la diagonale du carré contenant le cercle
dans ce cas, le test devrait être
if ( Ligne.ptSegDist(absCentre, ordCentre) < TaillePoteau/2*Math.sin(Math.PI/4))

de plus, les angles doivent être en radians donc ca aurait été
sin(Math.PI/4) (=racine(2)/2 ;-p)

cette fois, ca doît être bon !

A+
Dobeliou
[Il ne faut jamais jouer à saute-mouton avec une licorne]
Messages postés
28
Date d'inscription
mercredi 23 juin 2004
Statut
Membre
Dernière intervention
9 juillet 2004
5
En fait, je vois pas pourquoi tu changes les coordonnées du centre.
J'ai tout de même essayé mais je n'arrive pas à un bon résultat.
Pour TaillePoteau, voici comment je le gère :

private double TaillePoteau = 20;

public void AjoutPoteau (double abscisse, double ordonnee)
{
Ellipse2D poteau = new Ellipse2D.Double(abscisse, ordonnee, TaillePoteau, TaillePoteau);
PoteauListe.addElement(poteau);
}

Donc en le déclarant comme ça, je suppose que c'est le rayon puisque c'est le demi grand axe de l'ellipse.
Messages postés
28
Date d'inscription
mercredi 23 juin 2004
Statut
Membre
Dernière intervention
9 juillet 2004
5
Au fait, je viens d'aller voir ton site internet. J'ai pas pu trop y rester longtemps vu que j'ai des tuteurs de stage qui rodent mais ca m'a paru assez interessant. Je retournerais voir ca. Il y a l'air d'avoir des bonnes équations pour les fractales.
Messages postés
333
Date d'inscription
dimanche 25 mai 2003
Statut
Membre
Dernière intervention
23 novembre 2009
1
TaillePoteau désigne donc bien le diamètre du cercle

donc je maintiens ce que j'ai dit ;-p

public boolean IntersectsPoteau(Line2D Ligne)
{

int i, TailleMax = PoteauListe.size();
Ellipse2D poteau2;
double absHautGauche; // Coordonnées du point en haut à gauche de l'ellipse
double ordHautGauche;
double absCentre;
double ordCentre;

boolean Intersection = false;
i = 0;
for (i = 0; i < TailleMax; i++)
{
poteau2 = (Ellipse2D)PoteauListe.elementAt(i);
absHautGauche = poteau2.getX();
ordHautGauche = poteau2.getY();
absCentre = absHautGauche + (TaillePoteau/2);
ordCentre = ordHautGauche + (TaillePoteau/2);
if ( Ligne.ptSegDist(absCentre, ordCentre) < TaillePoteau/2)
{
Intersection = true;
}
}
return Intersection;

une autre question :
est-ce que tu regardes l'intersection avec le segment délimité par les 2 points de la ligne ?
si c'est le cas, alors il faut modifier le test pour qu'il tienne compte du cas où le segment est à l'interieur du cercle :
double x1 = ligne.getP1().getX();
double y1 = ligne.getP1().getY();
double x2 = ligne.getP2().getX();
double y2 = ligne.getP2().getY();
double d1 = Math.sqrt((x1-absCentre)*(x1-absCentre)+(y1-ordCentre)*(y1-ordCentre));
double d2 = Math.sqrt((x2-absCentre)*(x2-absCentre)+(y2-ordCentre)*(y2-ordCentre));
double dist1 = Math.min(d1, d2);
double dist2 = Math.max(d1, d2);
if (dist1<=TailleMax/2 && dist2>=TailleMax/2)
Intersection = true;

voila

au sujet de mon site, ca fait assez longtemps que je n'y ais pas touché et actuellement, je suis en pleine periode de concours, mais, promis!, dès que j'ai le temps, je le continue!

Salut

Dobeliou
[Il ne faut jamais jouer à saute-mouton avec une licorne]
Messages postés
28
Date d'inscription
mercredi 23 juin 2004
Statut
Membre
Dernière intervention
9 juillet 2004
5
ok, je vais voir ça après la pose de midi.
Merci pour ton aide.
Pour le segment à l'intérieur du cercle, dans mon sujet de stage, cela n'est pas physiquement possible.
Mais je vais tout tester pour voir si ca fonctionne mieux.