Utiliser un Canvas pour dessiner dedant, et générer une Image

Utiliser un Canvas pour dessiner dedant, et générer une Image - Java - Programmation

Marsh Posté le 06-06-2003 à 15:35:15    

Utiliser un Canvas pour dessiner dedant, et générer une BufferedImage, tout ceci sans l'afficher, jamais, ça vous choque ?
 
EDIT : en fait si ça se trouve, ça sert même à ça un Canvas, j'en sais rien, je n'ai jamais fait d'interface en Java (ni AWT, ni Swing).


Message édité par El_gringo le 06-06-2003 à 15:38:24
Reply

Marsh Posté le 06-06-2003 à 15:35:15   

Reply

Marsh Posté le 06-06-2003 à 15:40:04    

Heu ben j'ai pas de réponse mais je suis intéressé :D [:blueflag]


---------------
Le Tyran
Reply

Marsh Posté le 06-06-2003 à 15:57:38    

On peut le faire...mais il te faudra quand même un élément graphique affiché pour récupérer un contexte graphiquye valide, sinon, pas moyen....
 
En gros :  
 

Code :
  1. Canvas c = new Canvas();
  2. Image i = c.createImage(width, height);

 
 
Te donne une image nulle, si c n'est pas affiché....
 
Donc, si tu fais ça :  
 
 
 

Code :
  1. public class Test {
  2.     public static void main(String[] args) {
  3.         Frame f = new Frame();
  4.         Canvas c2 = new Canvas();
  5.         c2.setSize(new Dimension(200, 200));
  6.         f.add(c2);
  7.         f.pack();
  8.         f.show();
  9.         Canvas c = new Canvas();
  10.         c.setSize(new Dimension(200, 200));
  11.         Image i = c2.createImage(200, 200);
  12.         System.out.println(i);
  13.         Graphics g = i.getGraphics();
  14.         g.setColor(Color.red);
  15.         g.fillRect(50, 50, 100, 100);
  16.        
  17.     }

 
 
tu peux dessiner dans g, sans que i soit jamais affichée....Par contre, si tu enlèves le premier "paragraphe" de code, et que tu fais Image i = c.createImage(..) au lieu de Image i = c2.createImage()
 
ben tu te prendra une NullPointerException au moment du getGraphics.
 
Je sais, c'est pas clair!! :D

Reply

Marsh Posté le 06-06-2003 à 16:09:07    

gfive a écrit :


Je sais, c'est pas clair!! :D


 
Je crois. ça veut dire que, si je comptais faire ça dans une appli-web, côté serveur, c'est grillé, non ?
Parce que ça risque d'être un joyeux bordel sur le serveur...

Reply

Marsh Posté le 06-06-2003 à 16:10:19    

LetoII a écrit :

Heu ben j'ai pas de réponse mais je suis intéressé :D [:blueflag]  


 
T'as compris que ça découlair de l'autre topic que j'ai lancé:
http://forum.hardware.fr/forum2.ph [...] h=&subcat=

Reply

Marsh Posté le 06-06-2003 à 16:14:55    

El_gringo a écrit :


 
T'as compris que ça découlair de l'autre topic que j'ai lancé:
http://forum.hardware.fr/forum2.ph [...] h=&subcat=


 
non non  :sarcastic:


---------------
Le Tyran
Reply

Marsh Posté le 06-06-2003 à 16:24:13    

En fait, on peut le faire :  
 
comme ça :  
 
 

Code :
  1. public class Test {
  2.     public static void main(String[] args) {
  3.         Image i = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
  4.         Graphics g = i.getGraphics();
  5.         g.setColor(Color.red);
  6.         g.fillRect(50, 50, 100, 100);
  7. }

 
 
et là, tu as une image qui va bien, il te reste plus qu'à la sauver dans un fichier, ou en faire ce que tu veux..
Mais attention : si tu utilises un jdk < 1.4, et linux (ou unix) ça nécessitera d'installer X sur ton serveur.
 
Si tu utilises un jdk >= 1.4, en lancant ton appli avec l'option -Dheadless=true (ou qqchose comem ça) tu n'a pas besoin de X. En plus, avec la nouvelle API javax.imageio, tu pourra sauver ton image dans un fichier beaucoup plus facilement....
 
J'ai un autre exemple :  
 
 

Code :
  1. public void generateMap(File sourceFile, ArrayList tokens, String targetfile) throws AtchikException {
  2.  try {
  3.     BufferedImage source = ImageIO.read(sourceFile);
  4.      BufferedImage image = new BufferedImage(source.getWidth(),
  5.           source.getHeight(),
  6.           BufferedImage.TYPE_INT_RGB);
  7.      Graphics2D g = image.createGraphics();
  8.    
  9.      g.drawImage(source, 0, 0, g.getColor(), null);
  10.    
  11.      Iterator it = tokens.iterator();
  12.      while (it.hasNext()) {
  13.   ((WeatherMapToken) it.next()).draw(g);
  14.      }
  15.      File f = new File(targetfile);
  16.     if (extension.equalsIgnoreCase(".gif" )) {
  17.  try {
  18.      GIFEncoder encoder = new GIFEncoder(image);
  19.      encoder.Write(new FileOutputStream(f));
  20.  } catch (AWTException awt) {
  21.      Debug.err(awt);
  22.  }
  23.     } else if (extension.equalsIgnoreCase(".jpg" )) {
  24.  ImageIO.write(image, "JPG", f);
  25.     } else {
  26.  throw new AtchikException("[MapGenerator.generateMap] Cannot prepare "+extension+" images" );
  27.     }
  28.  } catch (IllegalArgumentException iae) {
  29.      Debug.err(iae);
  30.      throw new AtchikException(iae.toString());
  31.  } catch (IOException ioe) {
  32.      Debug.err(ioe);
  33.      throw new AtchikException(ioe.toString());
  34.  }
  35.      }

 
 
bon, je te détaille pas le code, mais en gros, ça dessine des objets (les Tokens) sur une image de fond (source), en utilisant la méthode draw(Graphics g) de chaque Token,  et ça sauve le résultat dans le fichier f, en GIF, en utilisant un GIFEncoder, qui est une librairie trouvée sur le net.

Reply

Marsh Posté le 06-06-2003 à 16:27:29    

LetoII a écrit :


non non  :sarcastic:  


 
Ho, ça va, c'était juste un moyen de caser un petit lien vers mon autre topic! :o

Reply

Marsh Posté le 06-06-2003 à 16:31:27    

El_gringo a écrit :


 
Ho, ça va, c'était juste un moyen de caser un petit lien vers mon autre topic! :o  


 
 :lol:


---------------
Le Tyran
Reply

Marsh Posté le 06-06-2003 à 16:35:32    

gfive a écrit :

En fait, on peut le faire :  
 
comme ça :  
 
 

Code :
  1. public class Test {
  2.     public static void main(String[] args) {
  3.         Image i = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
  4.         Graphics g = i.getGraphics();
  5.         g.setColor(Color.red);
  6.         g.fillRect(50, 50, 100, 100);
  7. }

 
 
et là, tu as une image qui va bien, il te reste plus qu'à la sauver dans un fichier, ou en faire ce que tu veux..
Mais attention : si tu utilises un jdk < 1.4, et linux (ou unix) ça nécessitera d'installer X sur ton serveur.
 
Si tu utilises un jdk >= 1.4, en lancant ton appli avec l'option -Dheadless=true (ou qqchose comem ça) tu n'a pas besoin de X. En plus, avec la nouvelle API javax.imageio, tu pourra sauver ton image dans un fichier beaucoup plus facilement....
 
J'ai un autre exemple :  
 
 

Code :
  1. public void generateMap(File sourceFile, ArrayList tokens, String targetfile) throws AtchikException {
  2.  try {
  3.     BufferedImage source = ImageIO.read(sourceFile);
  4.      BufferedImage image = new BufferedImage(source.getWidth(),
  5.           source.getHeight(),
  6.           BufferedImage.TYPE_INT_RGB);
  7.      Graphics2D g = image.createGraphics();
  8.    
  9.      g.drawImage(source, 0, 0, g.getColor(), null);
  10.    
  11.      Iterator it = tokens.iterator();
  12.      while (it.hasNext()) {
  13.   ((WeatherMapToken) it.next()).draw(g);
  14.      }
  15.      File f = new File(targetfile);
  16.     if (extension.equalsIgnoreCase(".gif" )) {
  17.  try {
  18.      GIFEncoder encoder = new GIFEncoder(image);
  19.      encoder.Write(new FileOutputStream(f));
  20.  } catch (AWTException awt) {
  21.      Debug.err(awt);
  22.  }
  23.     } else if (extension.equalsIgnoreCase(".jpg" )) {
  24.  ImageIO.write(image, "JPG", f);
  25.     } else {
  26.  throw new AtchikException("[MapGenerator.generateMap] Cannot prepare "+extension+" images" );
  27.     }
  28.  } catch (IllegalArgumentException iae) {
  29.      Debug.err(iae);
  30.      throw new AtchikException(iae.toString());
  31.  } catch (IOException ioe) {
  32.      Debug.err(ioe);
  33.      throw new AtchikException(ioe.toString());
  34.  }
  35.      }

 
 
bon, je te détaille pas le code, mais en gros, ça dessine des objets (les Tokens) sur une image de fond (source), en utilisant la méthode draw(Graphics g) de chaque Token,  et ça sauve le résultat dans le fichier f, en GIF, en utilisant un GIFEncoder, qui est une librairie trouvée sur le net.


 
Cool.
Là tu remet en question ce que tu disais au début, non !?
Pour la sauvegarde par contre, c'est bon. Je sauvegarde pas mes images, je les converti en tel ou tel format, les dimensionne correctement, les oriente correctement, et puis je les balances sur la sortie HTTP d'une servlet. ça, c'est déja géré avec des images générées plus "normalement" (simplement lues dans un fichier).
Merci...

Reply

Marsh Posté le 06-06-2003 à 16:35:32   

Reply

Marsh Posté le 06-06-2003 à 16:38:32    

ouais, je me remet en question, effectivement!! :D
J'avais oublié que j'avais fait ce machin truc... :p Ca fait plus d'un an, alors bon... :D

Reply

Marsh Posté le 06-06-2003 à 16:45:14    

Ha, mais par contre, là tu n'utilises pas de Canvas.
En fait, voila pourquoi je veux faire ça :
j'ai une image générée en C++ par JNI, et je voudrais en récupérer une BufferedImage. Le format "standard" d'images en C/C++, sous windows, et voila le code d'exmple que j'ai trouvé:

Code :
  1. /*
  2. * AWT Native Drawing Surface (JAWT_DrawingSurface).
  3. *
  4. * For each platform, there is a native drawing surface structure.  This
  5. * platform-specific structure can be found in jawt_md.h.  It is recommended
  6. * that additional platforms follow the same model.  It is also recommended
  7. * that VMs on Win32 and Solaris support the existing structures in jawt_md.h.
  8. *
  9. *******************
  10. * EXAMPLE OF USAGE:
  11. *******************
  12. *
  13. * In Win32, a programmer wishes to access the HWND of a canvas to perform
  14. * native rendering into it.  The programmer has declared the paint() method
  15. * for their canvas subclass to be native:
  16. *
  17. *
  18. * MyCanvas.java:
  19. */
  20. import java.awt.*;
  21. public class MyCanvas extends Canvas {
  22.      static {
  23.          System.loadLibrary("mylib" );
  24.      }
  25.      public native void paint(Graphics g);
  26. }
  27. /*************************************
  28. * myfile.c:
  29. */
  30. #include "jawt_md.h"
  31. #include <assert.h>
  32. JNIEXPORT void JNICALL
  33. Java_MyCanvas_paint(JNIEnv* env, jobject canvas, jobject graphics)
  34. {
  35.      JAWT awt;
  36.      JAWT_DrawingSurface* ds;
  37.      JAWT_DrawingSurfaceInfo* dsi;
  38.      JAWT_Win32DrawingSurfaceInfo* dsi_win;
  39.      jboolean result;
  40.      jint lock;
  41.      // Get the AWT
  42.      awt.version = JAWT_VERSION_1_3;
  43.      result = JAWT_GetAWT(env, &awt);
  44.      assert(result != JNI_FALSE);
  45.      // Get the drawing surface
  46.      ds = awt.GetDrawingSurface(env, canvas);
  47.      assert(ds != NULL);
  48.      // Lock the drawing surface
  49.      lock = ds->Lock(ds);
  50.      assert((lock & JAWT_LOCK_ERROR) == 0);
  51.      // Get the drawing surface info
  52.      dsi = ds->GetDrawingSurfaceInfo(ds);
  53.      // Get the platform-specific drawing info
  54.      dsi_win = (JAWT_Win32DrawingSurfaceInfo*)dsi->platformInfo;
  55.      //////////////////////////////
  56.      // !!! DO PAINTING HERE !!! //
  57.      //////////////////////////////
  58.      // Free the drawing surface info
  59.      ds->FreeDrawingSurfaceInfo(dsi);
  60.      // Unlock the drawing surface
  61.      ds->Unlock(ds);
  62.      // Free the drawing surface
  63.      awt.FreeDrawingSurface(ds);
  64. }

Reply

Marsh Posté le 06-06-2003 à 16:46:55    

bah, a ce moment là, tu modifies ça, pour te passer du Canvas, et tu utilises directement le Graphics, plutôt.....

Reply

Marsh Posté le 06-06-2003 à 16:56:50    

gfive a écrit :

bah, a ce moment là, tu modifies ça, pour te passer du Canvas, et tu utilises directement le Graphics, plutôt.....


 
Ben oui, j'suis bête moi.
C'est génial, je vais faire des trucs extraordinaires! :D  
Merci beaucoup.
 
EDIT : la Java est un langage génial ! :D


Message édité par El_gringo le 06-06-2003 à 16:57:19
Reply

Marsh Posté le 11-06-2003 à 09:47:13    

gfive a écrit :

bah, a ce moment là, tu modifies ça, pour te passer du Canvas, et tu utilises directement le Graphics, plutôt.....


 
Hé ben non, apparement, c'est n'est pas possible (ou alors je n'vois pas comment): pour faire ce que je veux, j'ai besoin d'une structure "JAWT_DrawingSurface" valide. Chose que je n'peux obtenir qu'en utilisant "GetDrawingSurface", qui prend pour paramètre un java.awt.Component.
Donc, j'en reviens à la question de départ ( :sweat: ):  
Je voudrais dessiner dans un Canvas, puis obtenir une BufferedImage de ce qui y à été dessiné. Tout ça, sans afficher ce fameux Canvas !
ça vous parait possible ? Comment ?

Reply

Marsh Posté le 11-06-2003 à 13:52:22    

baaaah...Tupeux instancier un Canvas sans l'afficher, hein...Mais tu aura toujours le problème qu'avec un JDK < 1.4, tu ne pourra pas obtenir une instance de Graphics à partir de ce machin là.....

Reply

Marsh Posté le 11-06-2003 à 14:29:05    

gfive a écrit :

baaaah...Tupeux instancier un Canvas sans l'afficher, hein...Mais tu aura toujours le problème qu'avec un JDK < 1.4, tu ne pourra pas obtenir une instance de Graphics à partir de ce machin là.....


 
C'est pas grave, regarde la méthode que j'ai postée : ils n'utilisent pas l'instance de Graphics. Elle est là juste pour correcpondre à la signature, parce qu'ils veulent redéfinir la méthode "paint" de leur Component. Moi, étant donne que c'est juste pour enregistrer une image (et non l'afficher), je pourrait me faire une autre méthode native (genre createJNIImage), sans paramètres, dans laquelle je ferait exactement la même chose que ce qu'ils font.
Reste à trouver comment obtenir un BufferedImage représentant le contenu de ce Canvas...

Reply

Marsh Posté le 12-06-2003 à 08:56:30    

Pas sur que ce soit des masses utile, mais je tente quand même un petit retour de topic...

Reply

Marsh Posté le 12-06-2003 à 09:59:23    

Et en faisant ça :  
 

Code :
  1. Canvas tonCanvas = new Canvas();
  2.   // dessin en natif
  3. Image i = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
  4. Graphics g = i.getGraphics();
  5.  
  6.   tonCanvas.paint(g);

 
 
ça suffirait pas???

Reply

Marsh Posté le 12-06-2003 à 10:57:48    

gfive a écrit :

Et en faisant ça :  
 

Code :
  1. Canvas tonCanvas = new Canvas();
  2.   // dessin en natif
  3. Image i = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
  4. Graphics g = i.getGraphics();
  5.  
  6.   tonCanvas.paint(g);

 
 
ça suffirait pas???


 
Heu, je sais pas vraiment.
Après avoir fait ça, mon Image i contient ce que j'ai dessiné dedant via la méthode paint ?

Reply

Marsh Posté le 12-06-2003 à 13:13:25    

Si t'as dessiné dedant, non.. Mais si t'as dessiné dedans, oui!! :D:D


Message édité par gfive le 12-06-2003 à 13:16:50
Reply

Marsh Posté le 12-06-2003 à 14:13:01    

gfive a écrit :

Si t'as dessiné dedant, non.. Mais si t'as dessiné dedans, oui!! :D:D


 
Heu, y aurait pas comme une erreur dans ce que t'as écrit là !? :??:  
Et moi j'reprend ce que j'ai dit :
Avec ce que tu m'a donné un p'tit peu au dessus, mon Image i contient ce que je dessine via la méthode paint ?

Reply

Marsh Posté le 12-06-2003 à 14:47:15    

Je te faisais juste remarquer que dedans prend un S à la fin, c'est tout!! :D:D
Mais sinon, oui, ça devrait marcher.
 
(Mais dans le bout de code que j'avais mis, te n'aura normalement pas à mettre de code à l'endroit où j'ai mis "//ton code en natif" parce que c'est fait par l'appel à tonCanvas.paint(g);
 
ouala.

Reply

Marsh Posté le 12-06-2003 à 15:00:05    

Ok, merci pour tout.
Dans l'immédiat, j'n'ai pas le temps d'essayer ça, mais dès que j'en saurais plus, je posterai ici pour dire ce qu'il en est bien sur. :hello:

Reply

Marsh Posté le 12-06-2003 à 15:02:17    

ouais, ça m'intéresse, la partie en natif C!! :)

Reply

Marsh Posté le 14-06-2003 à 13:21:57    

Juste un truc : je suis pas sur d'avoir bien tout compris, mais pour dessiner en win32, tu vas avoir besoin du HWND du composant, l'handle de sa fenetre ; et si le composant n'est pas affiché, pas de handle de fenetre. Je me trompe ?

Reply

Marsh Posté le 16-06-2003 à 10:50:18    

R3g a écrit :

Juste un truc : je suis pas sur d'avoir bien tout compris, mais pour dessiner en win32, tu vas avoir besoin du HWND du composant, l'handle de sa fenetre ; et si le composant n'est pas affiché, pas de handle de fenetre. Je me trompe ?


 
Pas besoin de HWND pour dessiner en Win32. Un Device Context (DC) suffira.

Reply

Marsh Posté le 23-06-2003 à 09:04:15    

El_gringo a écrit :


 
Pas besoin de HWND pour dessiner en Win32. Un Device Context (DC) suffira.


 
Arréte moi si je me trompe, ton DC tu le récupère pas à partir d'un Handle? (Ca fait un moment que j'ai pas utilisé ça j'ai un trou de mémoire :D)


---------------
Le Tyran
Reply

Marsh Posté le 23-06-2003 à 09:07:35    

LetoII a écrit :


 
Arréte moi si je me trompe, ton DC tu le récupère pas à partir d'un Handle? (Ca fait un moment que j'ai pas utilisé ça j'ai un trou de mémoire :D)


 
Si on veut dessiner dans une vue (ou un autre élément graphique), si, bien sur, il faut récupérer le DC à partir du handle de la fenêtre dans laquelle on veut dessiner. Mais on peut très bien utiliser un DC "virtuel" pour dessiner en mémoire seulement.

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed