[openGL 2D] afficher un simple bitmap sur une surface...

afficher un simple bitmap sur une surface... [openGL 2D] - Programmation

Marsh Posté le 21-05-2002 à 14:59:45    

voilà, j'ai besoin d'un truc assez simple : afficher un bitmap sur une surface dont on a le handle... (le tout sous win32)
 
le but ?
l'affichage d'un graphe en tps réel dans une application médicale : je dois pouvoir afficher 520 colonnes de 1*200 pixels en 4 secondes sans aucun ralentissement ...  
tout ce ke j'ai trouvé pour l'instant, c'est pour l'affichage en pleine fenêtre/écran et je ne trouve pas comment le faire sur une surface simple.
 
 :jap:


---------------
Boolay for ever...
Reply

Marsh Posté le 21-05-2002 à 14:59:45   

Reply

Marsh Posté le 21-05-2002 à 16:36:36    

l'affichage windows n'est pas assez rapide ? c'est assez petit comme surface. tu crées une hbitmap de 200*520, tu écris dedans, puis tu blittes ... t'as essayé au moins ? :D
 
sinon:
 
* tu alloues un buffer de 200*520, tu le remplis "à la main" avec tes lignes, tu l'uploades en tant que texture et hop.
 
* ou un buffer de 200*1 si les lignes sont identiques, un upload et 520 affichages.
 
enfin je suis pas sûr de bien comprendre.

Reply

Marsh Posté le 21-05-2002 à 16:42:40    

En effet, 4 secondes t'as tout le temps de construire et afficher un bitmap de cette taille sans passer par opengl.
Ça doit prendre même pas 0.5 seconde...


---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
Reply

Marsh Posté le 21-05-2002 à 16:52:04    

non, non... c pas suffisant...
faut ke j'affiche colonne après colonne... une colonne faisant 1 pixel...  
 
et le tout à plus de 150 frames/sec pour ke ça soit fluide...
en fait, l'affichage kon utilise actuellement utilise le TPaintBox de delphi ki lui même utilise ... win32... (?) et ça a tendance à saccader de tps en tps... résultat : client pas content et client plus vouloir acheter nos produits et pov' developpeur ke je suis devoir trouver solution en très peu de tps....
 
j'ai aussi essayé d'afficher avec win32 dans un p'tit prog en C et c'était trop lent...  
 
non, mais en fait, je pense avoir trouvé pour afficher une bitmap en openGL... faudrait juste ke je trouve comment lui dire d'afficher dans une surface définie par un handle... c juste une fonction ki me manke koi... (eu.. non ?)


---------------
Boolay for ever...
Reply

Marsh Posté le 21-05-2002 à 17:00:56    

antp a écrit a écrit :

En effet, 4 secondes t'as tout le temps de construire et afficher un bitmap de cette taille sans passer par opengl.
Ça doit prendre même pas 0.5 seconde...  




 
 
avec openGL, il en faut env 0.2 sec (difficile à mesurer en fait ;) )  
et oui, avec win32, ça prend preske autant de tps... mais si t'affiches le tout en même tps... pas si tu affiches colonne après colonne... maintenant, j'ai p'têtre codé mon truc comme un gros porcasse mais bon... c le genre de truc ki fé 15 lignes...
je vous aurais bien foutu le code mais je crois l'avoir détruit...
j'avais aussi essayé avec openPTC, tiens, ki est censé être optimisé à fond... et toujours trop lent...  
là, l'affiche openGL me convient... mais je ne le veux pas dans une fenêtre mais dans une surface contenue dans une fenêtre...
 
antp, toi ki connait delphi (et les autres aussi, d'ailleurs ;) ), j'vais essayer d'être plus clair :
 
je v mettre un composant dans ma fenêtre (style PaintBox...).
je veux créer une dll ki me permettra :
1. d'initialiser openGl pour le composant paintBox (en utilisant son handle windows);
2. afficher une colonne de pixel (chaque pixel de cette colonne peut avoir une colonne différente)
3. "vider" la surface : la remplir de noir, koi....
 
... voyez ?
 
 
bon, pour essayer d'être un peu moins flou.... : voilà la gueule du logiciel  :gun:  :  
 
http://membres.lycos.fr/clancsicn/diadop.jpg
 
les deux rectangles noirs sont les composants devant afficher les spectres...

 

[jfdsdjhfuetppo]--Message édité par Moustaaki le 21-05-2002 à 17:09:41--[/jfdsdjhfuetppo]


---------------
Boolay for ever...
Reply

Marsh Posté le 21-05-2002 à 17:06:41    

Moustaaki a écrit a écrit :

et le tout à plus de 150 frames/sec pour ke ça soit fluide...


argument de quaker (= argument nul).
 
fréquence de rafraîchissement de L'ECRAN != fréquence de rafraîchissement de L'APPLICATION
 
il n'y a absolument AUCUN interêt à afficher un truc à 150 fps alors que ton moniteur doit tourner à 80hz à tout casser.

Moustaaki a écrit a écrit :

comment lui dire d'afficher dans une surface définie par un handle


faut 'locker' la bitmap avec CreateCompatibleDC & co, ce qui risque d'être assez lent. le + rapide est de faire le painting toi-même dans un buffer ET DE L'AFFICHER AVEC WIN32, en passant par une DIB par ex. si tu ne maitrises pas la gui, n'espère pas la solution miracle avec opengl.

Reply

Marsh Posté le 21-05-2002 à 17:07:22    

ps : si tu veux une réponse spécifique, pose une question spécifique (voici mon code, ça rame quand je fais ça, comment optimiser ?)

Reply

Marsh Posté le 21-05-2002 à 17:12:32    

youdontcare a écrit a écrit :

ps : si tu veux une réponse spécifique, pose une question spécifique (voici mon code, ça rame quand je fais ça, comment optimiser ?)  




 
 
ok, g ça :
 

Code :
  1. #include "glut.h"
  2. void winInit(){
  3.     /* Set system of coordinates */
  4.     gluOrtho2D(0.0, 520, 0.0, 200);
  5. };
  6. void display(void){
  7.     const int    NumberSteps = 1000;
  8.     const int    NumberOrbits = 100;
  9.     const double Delta_x = pi2/(NumberOrbits-1);
  10.     int step, orbit;
  11. float r, g, b;
  12. r=0.0;g=0.0;b=0.0;
  13.     glColor3f(0.0, 0.0, 0.0);
  14.     glClear(GL_COLOR_BUFFER_BIT);
  15.     glColor3f(r, g, b);
  16. double x, y;
  17. x = 0;
  18. glBegin(GL_POINTS);
  19. for (orbit = 0; orbit < 523; orbit++)
  20. {
  21.  x = orbit;
  22.  if (r == 1.0) r=0.0; else r+=0.001;
  23.  if (g == 1.0) g=0.0; else g+=0.002;
  24.  if (b == 1.0) b=0.0; else b+=0.001;
  25.  glColor3f(r, g, b);
  26.  for (step = 0; step < 200; step++)
  27.  {
  28.   y=step;
  29.   glVertex2f(x, y);
  30.  }
  31. }
  32.   glEnd();
  33.    };
  34. int main(int argc, char **argv) {
  35.   glutInit(&argc, argv); 
  36.   glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA); 
  37.   glutInitWindowPosition(5,5); 
  38.   glutInitWindowSize(520,200); 
  39.   glutCreateWindow("Standard Map" ); 
  40.  
  41.   winInit();
  42.   glutDisplayFunc(display); 
  43.   glutMainLoop(); 
  44.  
  45.   return 0; 
  46. }


 
 
comment je fé pour kil l'affiche dans une surface délimitée par un handle au lieu de l'afficher dans une fenêtre séparée ?

 

[jfdsdjhfuetppo]--Message édité par Moustaaki le 21-05-2002 à 17:33:09--[/jfdsdjhfuetppo]


---------------
Boolay for ever...
Reply

Marsh Posté le 21-05-2002 à 17:14:56    

youdontcare a écrit a écrit :

faut 'locker' la bitmap avec CreateCompatibleDC & co, ce qui risque d'être assez lent. le + rapide est de faire le painting toi-même dans un buffer ET DE L'AFFICHER AVEC WIN32, en passant par une DIB par ex. si tu ne maitrises pas la gui, n'espère pas la solution miracle avec opengl.  




 
 
kan je disais 150  fps, c'est par ceke je fé le calcul simple (et naïf apparement) : 520/4 sec = 125 ... donc pour être sûr ke ça rame po => 150....
 
je te retrouve le code win32 et je te le mêt pour ke tu me dises ce ke je peux optimiser....

 

[jfdsdjhfuetppo]--Message édité par Moustaaki le 21-05-2002 à 17:16:10--[/jfdsdjhfuetppo]


---------------
Boolay for ever...
Reply

Marsh Posté le 21-05-2002 à 17:15:36    

Je connais pas opengl :/
 
Sinon le prob c'est quoi ? Que c'est lent ou que ça clignote lors du rafraîchissement ? Si c'est le second cas il suffit d'activer l'attribut DoubleBuffer de la form ou du panel où est dessinée l'image. ça bouffe plus de ram mais ça évite les clignotements.
 
PS : pas beau le screenshot en jpeg :D http://www.antp.be/PNG/


---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
Reply

Marsh Posté le 21-05-2002 à 17:15:36   

Reply

Marsh Posté le 21-05-2002 à 17:21:39    

antp a écrit a écrit :

Je connais pas opengl :/
 
Sinon le prob c'est quoi ? Que c'est lent ou que ça clignote lors du rafraîchissement ? Si c'est le second cas il suffit d'activer l'attribut DoubleBuffer de la form ou du panel où est dessinée l'image. ça bouffe plus de ram mais ça évite les clignotements.
 
PS : pas beau le screenshot en jpeg :D http://www.antp.be/PNG/  




 
 
le pb, c ke l'affichage s'arrêtent et ke genre 50 colonnes de pixels sont affichées d'un coup...
 
 
(Ps : eu.. oui... dsl ;) pov' gimp, il a du souffir avec ce jpg ;) )


---------------
Boolay for ever...
Reply

Marsh Posté le 21-05-2002 à 17:22:52    

Ha ouais c'est plus de l'animation là ... :/
Y a pas des composants Delphi spécialisés pour ça ? Ça doit sûrement exister


---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
Reply

Marsh Posté le 21-05-2002 à 17:24:52    

antp a écrit a écrit :

Ha ouais c'est plus de l'animation là ... :/
Y a pas des composants Delphi spécialisés pour ça ? Ça doit sûrement exister  




 
... ? pas dans les composants de base en tout cas... ?
 
 
udontcare, v'là un p'tit test ki affiche des pixels colonne après colonne. ce test utilise openPTC ki est censé être optimisé et donc plus rapide ke win32 (d'après ce ke j'ai compris et certainement avec une bonne utilisation de celui-ci) :
 
donc, ça donne ceci :
 
initialisation de la "chose" :

Code :
  1. HWND item = GetDlgItem(hDialog, ID_RECTANGLE);
  2. Format format(32,0x00FF0000,0x0000FF00,0x000000FF);
  3. Surface surface(480, 200, format);
  4. int32 *pixels = (int32*) surface.lock();
  5. const int r = 256;
  6. const int g = 256;
  7. const int b = 256;
  8. for (int x=0; x<480; x++)
  9. {
  10.  for (int y= 0; y<200; y++)
  11.  {
  12.   pixels[x+y*480] = (r<<16) + (g<<8) + b;
  13.  }
  14. }
  15. surface.unlock();
  16. surface.copy(item);


 
bon, ensuite la p'tite boucle ki affiche mes colonnes (dans une console, ça peut-être ça ki fait ramer ?)
 

Code :
  1. Console console;
  2. try
  3. {
  4.         Format format(32,0x00FF0000,0x0000FF00,0x000000FF);
  5.         console.open("Random example",format);
  6. Surface surface(console.width(), console.height(), format);
  7. while (!console.key())
  8. {
  9.  // get surface dimensions
  10.  const int width  =console.width();
  11.  const int height = console.height();
  12.  const int r = random(256);
  13.  const int g = random(256);
  14.  const int b = random(256);
  15.  for (int x=0; x<width; x++)
  16.  {
  17.   int32 *pixels = (int32*) surface.lock();
  18.   for (int y=0; y<height; y++)
  19.   {
  20.    // draw color [r,g,b] at position [x,y]
  21.    pixels[x+y*width] = (r<<16) + (g<<8) + b;
  22.   }
  23.   // unlock surface
  24.   surface.unlock();
  25.   // copy to console
  26.   surface.copy(console);
  27.   console.update();
  28.  }
  29.  surface.clear();
  30. }
  31. }
  32. catch(Error &error)
  33. {
  34.  console.close();
  35.  error.report();
  36.  ExitThread(-1);
  37.  return(-1);
  38. }
  39. console.close();
  40. ExitThread(0);

 

[jfdsdjhfuetppo]--Message édité par Moustaaki le 21-05-2002 à 17:32:40--[/jfdsdjhfuetppo]


---------------
Boolay for ever...
Reply

Marsh Posté le 21-05-2002 à 17:25:09    

Moustaaki a écrit a écrit :

comment je fé pour kil l'affiche dans une surface délimitée par un handle au lieu de l'afficher dans une fenêtre séparée ?


tu "fé" pas. tu veux utiliser un porte-avions pour ouvrir une boîte de conserve. donc tu arrêtes de "fére" nimpe et tu testes du code win32 de base qui est prévu pour ça :
 
http://msdn.microsoft.com/library/ [...] s_233i.asp
 
ça te crééra une HBITMAP que tu pourras accéder "en direct". maintenant si tu pouvais dire quel genre de truc tu veux afficher ... :lol: mais en gros, tu cuisines avec le buffer que te file CreateDIBSection(), puis dès que tu as fini le painting, tu fais un BitBlt() dans la fenêtre d'affichage.

Moustaaki a écrit a écrit :

kan je disais 150  fps, c'est par ceke je fé le calcul simple (et naïf apparement) : 520/4 sec = 125 ... donc pour être sûr ke ça rame po => 150....


edit : j'avais mal compris (décidément ...). donc oui, 520/4 sec = 125 "fps". je te le dis tout de suite, ça ne "marchera" jamais. si ton moniteur est à une résolution de 80hz, tu auras 80 images, point.

 

[jfdsdjhfuetppo]--Message édité par youdontcare le 21-05-2002 à 17:27:15--[/jfdsdjhfuetppo]

Reply

Marsh Posté le 21-05-2002 à 17:30:10    

Moustaaki a écrit a écrit :

 
 
... ? pas dans les composants de base en tout cas... ?  




 
Bhen non mais bon il existe peut-être 100 ou 1000x plus de composants que ce qui est fourni avec Delphi....
www.torry.net
j'ai vaguement cherché mais pas trouvé, mais bon j'ai un machin en SQL à terminer...


---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
Reply

Marsh Posté le 21-05-2002 à 17:33:45    

antp a écrit a écrit :

 
 
Bhen non mais bon il existe peut-être 100 ou 1000x plus de composants que ce qui est fourni avec Delphi....
www.torry.net
j'ai vaguement cherché mais pas trouvé, mais bon j'ai un machin en SQL à terminer...  




 
oki, merci bp  :jap:


---------------
Boolay for ever...
Reply

Marsh Posté le 21-05-2002 à 17:37:48    

bon, dsl de faire une fixation sur l'openGL mais j'ai p'têtre trouvé mon bonheur :
TGLPaintBox  SW 193 Kb 3 Jul 2001  
By Microolap Technologies LLC. PaintBox with OpenGL support. Allows you easily add various 3D effects to your applications.  
This component has several methods which allows you show graphic primitives:  
 
 
 
arg, mais :
Demo only
Source: On purchase/registration


---------------
Boolay for ever...
Reply

Marsh Posté le 21-05-2002 à 23:14:07    

Ce programme capture le son du micro d'une carte son, effectue une transformée de Fourier à chaque capture, et affiche le tout sous 2 graphiques (1 qui montre la capture l'autre la FFT)
http://www.chez.com/regatbar/freq/freq.png
Il peut aller jusqu'à 172 fps, et ca marche tres bien ...
Sachant qu'une transformée de Fourier c'est assez couteux en temps machine, on peut donc considérer que ce programme bien que la courbe principale soit en 285x161 serait largement capable d'afficher tes spectres ... et il est codé en Win32 pur, sans OpenGL, en utilisant les fonctions de bases !
Car au rique de te décevoir, Windows utilise les possibilités hardware 2D de ta carte video pour tout ce qui est tracer des lignes, blitter, afficher un curseur, ...
Donc à mon avis avec OpenGL ou quoique ce soit tu ne gagneras rien !
Penches toi sérieusement sur une solution moins complexe (faut livrer les dll OpenGL + Glut ...). openPTC a l'air pas mal. Mais j'ai l'impression, sans rien y connaître, que tu ne l'utilises pas très bien ... ;)
 

Code :
  1. HWND item = GetDlgItem(hDialog, ID_RECTANGLE); 
  2. Format format(32,0x00FF0000,0x0000FF00,0x000000FF);
  3. Surface surface(480, 200, format);
  4. int32 *pixels = (int32*) surface.lock(); 
  5. const int r = 256; // <-- 255 plutot non ?
  6. const int g = 256;
  7. const int b = 256;
  8. for (int x=0; x<480; x++)
  9. {
  10. for (int y= 0; y<200; y++)
  11. {
  12.   pixels[x+y*480] = (r<<16) + (g<<8) + b;
  13. }
  14. }
  15. surface.unlock();
  16. surface.copy(item);


 
Se résume à :

Code :
  1. HWND item = GetDlgItem(hDialog, ID_RECTANGLE); 
  2. Format format(32,0x00FF0000,0x0000FF00,0x000000FF);
  3. Surface surface(480, 200, format);
  4. int32 *pixels = (int32*) surface.lock();
  5. memset(pixels, 0x00FFFFFF, 480 * 200 * sizeof(int32));
  6. surface.unlock();
  7. surface.copy(item);


 
Windows possède des fonctions pour obtenir le même résultat (PatBlt sur un bitmap ...) qui elles utiliseront surement des accelerations 2D.
 
Ce code peut d'ailleur être supprimé puisqu'ensuite toute l'image est initialisée ...
 

Code :
  1. while (!console.key())
  2. {
  3. // get surface dimensions  
  4. const int width  =console.width();
  5. const int height = console.height();
  6. const int r = random(256);
  7. const int g = random(256);
  8. const int b = random(256); 
  9. for (int x=0; x<width; x++)
  10. {
  11.   int32 *pixels = (int32*) surface.lock();
  12.   for (int y=0; y<height; y++)
  13.   {
  14.    // draw color [r,g,b] at position [x,y]  
  15.    pixels[x+y*width] = (r<<16) + (g<<8) + b;
  16.   }
  17.   // unlock surface  
  18.   surface.unlock();
  19.   // copy to console  
  20.   surface.copy(console);
  21.   console.update();
  22. }
  23. surface.clear();
  24. }


 
Ne peux-tu pas sortir les fonctions en bleu de ce for(;;) et ainsi économiser width appels à ces fonctions ?
 
Il y aurait aussi une petite optimisation à faire en definissant un tableau de 4 octets {a|r|g|b} qui pourrait se faire passer pour un int32 et optimiser un chouilla l'affectation à pixels (color.rgb[0] = random(256); color.rgb[1] = random(256); color.rgb[2] = random(256); ... pixels[x+y*width] = color.int_32;)
mais c'est presqu'insignifiant (quoique rapportée à plusieurs dizaines de milliers de fois par secondes ...)
 
Si ton souhait est de tracer une courbe telle que celle du logiciel ci-dessus en haut à droite, il existe sous Windows des fonctions dédiée à ça : tu leur file un tableau de points (x, y) et elle te tracent la courbe (PolyLine, PolyBezier, ...).
Elles sont très rapides. J'avais pour mon projet (afficheage de courbes + spectres :)) il y a un an mesuré les temps nécessaires pour tracer une courbe d'environ 1 millier de points, le temps était d'une dizaines de millisecondes (sur un pentium II)


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 22-05-2002 à 09:48:50    

HelloWorld a écrit a écrit :

 
...
Ne peux-tu pas sortir les fonctions en bleu de ce for(;;) et ainsi économiser width appels à ces fonctions ?
 
Il y aurait aussi une petite optimisation à faire en definissant un tableau de 4 octets {a|r|g|b} qui pourrait se faire passer pour un int32 et optimiser un chouilla l'affectation à pixels (color.rgb[0] = random(256); color.rgb[1] = random(256); color.rgb[2] = random(256); ... pixels[x+y*width] = color.int_32;)
mais c'est presqu'insignifiant (quoique rapportée à plusieurs dizaines de milliers de fois par secondes ...)
 
Si ton souhait est de tracer une courbe telle que celle du logiciel ci-dessus en haut à droite, il existe sous Windows des fonctions dédiée à ça : tu leur file un tableau de points (x, y) et elle te tracent la courbe (PolyLine, PolyBezier, ...).
Elles sont très rapides. J'avais pour mon projet (afficheage de courbes + spectres :)) il y a un an mesuré les temps nécessaires pour tracer une courbe d'environ 1 millier de points, le temps était d'une dizaines de millisecondes (sur un pentium II)  




 
 
en fait le code ke j'ai mi là est loin d'être le final :
le remplissage de la zone ne se fait en effet pas en boucle : il faut attendre les données reçus par USB, les traiter, les afficher... :)
 
ainsi, je serais boliG de faire width appels à ces fonctions puisqu'à chaque paquet reçu correspond une colonne. Il me semblait donc que cette boucle pourrait représenter la vitesse max d'affichage.... (mais comme je prog comme une merde ;) )
 
 je vais suivre kan même votre conseil d'utiliser win32 bien que je ne suis pas bon dans tout ce ki est opti, etc.... :(   pour la couleur, c'est pareil, c'est traité par le prog delphi avant d'être envoyé à l'affichage... ('fin, c'est comme ça que je le conçois pour l'instant... yaura certainement des modifications utltérieures)
 
tiens, voilà le style de spectre que ça doit donner puiske tu te demandais kel type de courbe ça affichait (bon, je te le mêt en png, antp :D )
 
http://membres.lycos.fr/clancsicn/spectre.png

 

[jfdsdjhfuetppo]--Message édité par Moustaaki le 22-05-2002 à 10:11:02--[/jfdsdjhfuetppo]


---------------
Boolay for ever...
Reply

Marsh Posté le 22-05-2002 à 10:36:33    

:lol: bon, ça me fait rire, ça rien à voir mais en faisant une petite recherche sur msdn avec les mots clés win32 drawing, j'obtient ça :
 
 
"Best Bets results for Win32
 
    Win32 Error Codes"
 
 
l'association win32 -> error me parait assez objective ;)


---------------
Boolay for ever...
Reply

Sujets relatifs:

Leave a Replay

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