EFFET D'EAU AVEC GETDIBITS ET SETDIBITS

florenth - 25 avril 2007 à 17:10
cs_mcapp Messages postés 71 Date d'inscription vendredi 3 novembre 2000 Statut Membre Dernière intervention 15 décembre 2011 - 30 juil. 2008 à 13:34
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/42445-effet-d-eau-avec-getdibits-et-setdibits

cs_mcapp Messages postés 71 Date d'inscription vendredi 3 novembre 2000 Statut Membre Dernière intervention 15 décembre 2011
30 juil. 2008 à 13:34
OK ! Merci Barbichette !
Pb corrigé ! Je vais pouvoir apprécier la qualité de travail !
Merci !
cs_barbichette Messages postés 220 Date d'inscription lundi 30 octobre 2000 Statut Membre Dernière intervention 15 juillet 2013
30 juil. 2008 à 09:32
dans les options de delphi, il doit y avoir un truc pour corriger ça.
Je ne sais plus où...
essaie déjà :
getmem(pointer(vagues),wi*he*2*2);
cs_mcapp Messages postés 71 Date d'inscription vendredi 3 novembre 2000 Statut Membre Dernière intervention 15 décembre 2011
30 juil. 2008 à 02:31
bonjour,
j'ai "types incompatibles" ligne 215 !
cs_Forman Messages postés 600 Date d'inscription samedi 8 juin 2002 Statut Membre Dernière intervention 6 avril 2010 1
25 août 2007 à 19:17
Ah oui: l'équivalent du malloc du C en Delphi c'est GetMem (peut être que le rapport est plus clair comme ça).
cs_Forman Messages postés 600 Date d'inscription samedi 8 juin 2002 Statut Membre Dernière intervention 6 avril 2010 1
25 août 2007 à 19:14
Ben si quand même ça a à voir, si tu lis à partir de la 3° phrase:

"The changes in this release are as follows:
Fixes an fxkeyboard.cpp build problem on Windows and a sporadic core
dump due to SetDIBits() reacting poorly to malloc()-allocated memory.
It is now using VirtualAlloc() instead of malloc(), which gives whole
pages. "

ça veut dire qu'ils ont corrigé un bug dans leur programme en utilisant "VirtualAlloc() instead of malloc()"
cs_jpt Messages postés 7 Date d'inscription samedi 12 octobre 2002 Statut Membre Dernière intervention 25 août 2007
25 août 2007 à 18:39
Hi !

@Barbichette :
Malheureusement, j'ai maintenant un bug à la fermeture

M'en suis sorti avec SetLength(vagues, wi*he*2*2); plutôt que le GetMem d'origine.
Et il y a un truc qui sert à rien :
//?? image1.Picture.Bitmap := tbitmap.Create;
Et Memcheck est pas content du tout si je décommente, ;-)

Dommage qu'il n'y ait pas plus de commentaires, difficile de démonter pour comprendre (et régler ce problème de "dépassement des limites" qui apparaît dans le timer si l'option est activée -- et si elle ne l'est pas, qu'est-ce que ça cache ?)
Bravo pour l'effet visuel, en tout cas !
cs_Forman Messages postés 600 Date d'inscription samedi 8 juin 2002 Statut Membre Dernière intervention 6 avril 2010 1
5 mai 2007 à 10:56
Oui effectivement ça doit être un problème d'écriture à l'extérieur d'un tableau. Je n'ai pas regardé en détails, mais en faisant ça:

WinGetMem(Pointer(im),wi*he*4*2*2);

au lieu de :

WinGetMem(Pointer(im),wi*he*4*2);

ça règle apparemment le problème (mais ça utilise 2x plus de mémoire aussi :-S)
cs_barbichette Messages postés 220 Date d'inscription lundi 30 octobre 2000 Statut Membre Dernière intervention 15 juillet 2013
5 mai 2007 à 01:03
Alors,
Mauricio, je vais voir pour faire un exemple plus simple,
Forman, j'ai essayé de mettre tes fonctions wingetmem et winfreemem à la place de getmem et freemem.
Malheureusement, j'ai maintenant un bug à la fermeture. Soit, j'écris en dehors d'un tableau, soit il y a un autre bug.
Je vais chercher le problème avant de poster la modif.
Merci pour l'info, c'est sûr que je n'aurai jamais cherché ici un bug pour des images plus grande...

a+
cs_MAURICIO Messages postés 2106 Date d'inscription mardi 10 décembre 2002 Statut Modérateur Dernière intervention 15 décembre 2014 5
4 mai 2007 à 16:21
Salut Barbichette,

j' avoue que ton source m' a bleuffé en terme de rapidité d' execution.
Par contre, difficile t' en tirer quelques chose vu la complexité du code.

Pourrais tu donner une nouvelle source d' utilisation de GetDiBits/SetDiBits beaucoup plus simple pour que l' on puisse plus facilement exploiter ces fonctions(et prendre en consideration le post de notre expert en images que je nomme Forman)?
Genre, on clique sur un bitmap et le bitmap subit une quelconque transformation dans la zone du clique (effet flou par exemple) ?

En tout cas, c' est du bon boulot!
A+
cs_Forman Messages postés 600 Date d'inscription samedi 8 juin 2002 Statut Membre Dernière intervention 6 avril 2010 1
26 avril 2007 à 16:17
Salut,

ton code fonctionne avec les images fournies, mais je pense que
1/Tu as de la chance.
2/Ce ne serait pas le cas avec des images de taille différente (en particulier plus grande).

Je m'explique: les fonctions GetDIBits et SetDIBits travaillent avec des pointeurs vers un tableau de pixels. Bien que ce ne soit précisé nulle part sur MSDN, et pour des raisons connues de Microsoft seules (à supposer qu'il y en ait vraiment, d'ailleurs) le tableau qu'on leur passe en paramètre doit être situé sur une seule page de la mémoire virtuelle (il ne doit pas chevaucher 2 pages par exemple).

La fonction native de Delphi que tu utilises ici, GetMem à la ligne 175:
getmem(cailloux,bit.Width*bit.Height*4);
ne garantit absolument pas ce comportement-là. Pour être sûr que ça fonctionne, il existe une méthode:

procedure WinGetMem(var p:Pointer;Size:Cardinal);
begin
p:=VirtualAlloc(nil,Size,MEM_COMMIT or MEM_RESERVE,PAGE_READWRITE);
if not Assigned(p) then
RaiseLastOSError;
end;

procedure WinFreeMem(p:Pointer);
begin
if Assigned(p) and not VirtualFree(p,0,MEM_RELEASE) then
RaiseLastOSError;
end;

En utilisant respectivement WinGetMem et WinFreeMem à la place de GetMem et FreeMem ça fonctionnera de la même façon et ça rendra ton code plus sûr. Essaie avec des images de taille plus grande, pas exemple 800x600 et tu verras que tu auras sûrement un problème (je le sais pour avoir passé des heures à m'arracher les cheveux pour essayer de comprendre pkoi ça marchait pas avec l'un de mes codes). Ce problème est pas exemple mentionné implicitement ici:
http://lists.ibiblio.org/pipermail/sm-spell-submit/2006-April/003307.html

En plus de corriger un éventuel bug, ça pourrait même accélérer ton code.
Francky23012301 Messages postés 400 Date d'inscription samedi 6 août 2005 Statut Membre Dernière intervention 11 février 2016 1
26 avril 2007 à 12:03
Salut,

L'effet est superbe et coté code pas grand chose à redire.

Juste une petite remarque : quand on fait ce genre de chose (effets graphiques), il serait toujours intéressant de faire initialement un petit commentaire pour expliquer le principe, la stratégie, ainsi que les formules utilisées, hors c'est rarement le cas et ca manque cruellement.

@+
cs_barbichette Messages postés 220 Date d'inscription lundi 30 octobre 2000 Statut Membre Dernière intervention 15 juillet 2013
25 avril 2007 à 20:49
je vais donc regarder les problèmse d'allocation, même si au finale, il ne prend en gros que 6Mo en mémoire, mais pour une programmation propre, no problemo.

Pour la forme de la pierre, je vais me pencher aussi sur le problème.
A l'origine, je pensais que la pierre restait sous l'eau lors du déplacement, mais avec un effet de bord, ça serai surement plus joli...

Je poste tout ça d'ici peu...

Sinon, pour les 75% de CPU, c'est souvent le cas pour les effets visuelles comme ceux là... ça paraît rien comme ça mais ça bouf pas mal de cpu.
On peut d'ailleurs optimiser le tout en assembleur mais pour la lecture des néofites, bof bof...

Bon, merci a tous, même si, il faut bien le dire, cet effet n'a rien de révolutionnaire...
En effet tout s'explique avec le problème du tableau +!
Pour ceux chez qui ça marche pas:
- Désactivez la gestion des limites (Projet > Options > Compilo)
- Compilez (Ctrl-F9)
- Construisez (Maj-F9)

Et il ne faut PAS oublier de faire les deux sinon ça marche pas ....

Du coup, je te re-félicite pour cette source. En effet le rendu est très beau même si j'ai dû ajouter un "DoubleBuffered := True" pour éviter les scintillements.

"il me semblait que la libération était automatique lorsque l'on sort de la porté de cette objet"

> Non non non, ceci n'est valide que pour les interfaces, qui gèrent leur cycle de vie avec les procédures _AddRef() et _ Release() ! Pour les objets, tu DOIOT impérativement les libérer quand tu ne t'en sers plus ! Sinon, gare aux fuites !

De la même façon que tout New() se traduit par un Dispose(), tout GetMem() se traduit par un FreeMem(), SetLength() se traduit par un Finalize() ou autre.

Et pareil, tout TObject.Create se suit d'un appel à Free, sauf s'il est réalisé implicitement, à savoir :
- Composant avec propriétaire (Owner <> nil)
- Objet référencé par au moins une interface.

En tout cas, je te re-re-félicite pour l'effet.
Juste un bémol: lorsqu'on déplace les cailloux, l'onde de propagation part du curseur de la souris alors qu'en réalité elle épouse les bords de la pierre en question ...

++
Flo
Harvester_ Messages postés 36 Date d'inscription vendredi 31 décembre 2004 Statut Membre Dernière intervention 8 juillet 2007
25 avril 2007 à 20:09
Très beau mais consomme énormément niveau CPU... 75% qui passe à presque 100 avec le Tsunami... P4 2Ghz...
Ali_usto Messages postés 131 Date d'inscription lundi 20 novembre 2006 Statut Membre Dernière intervention 11 octobre 2010
25 avril 2007 à 19:57
SALUT , bravo l'effet est vraiment tres joli et ça marche tres bien chez moi
bonne continuation...
cs_barbichette Messages postés 220 Date d'inscription lundi 30 octobre 2000 Statut Membre Dernière intervention 15 juillet 2013
25 avril 2007 à 19:08
pour l'erreur d'étendu, on peut remplacer array[0..0] par array[0..MAXINT div 4]
Et normalement, il n'y a plus de problème.

Sinon, Cirec, il me semblait que la libération était automatique lorsque l'on sort de la porté de cette objet.
Ainsi, quand on quitte une procédure, un object tbitmap ou autre créé dans cette procédure, l'objet est détruit à la sortie de cette procédure.
Peut-être que c'est que dans Borland, ou alors, ça n'existe plus, ou alors, j'ai rêvé...
Ahhh zut ! ça recommence ....
Des fois tout fonctionne chez moi mais pas chez les autres (oui tu as compris Cirec ^^) et là, maintenant, c'est l'inverse.

Par contre, ça me fait penser que j'ai oublié de te féliciter pour l'effet, car d'après la capture, ça rend déjà très bien.
Utilisateur anonyme
25 avril 2007 à 18:50
Salut,

chez moi j'ai pas le problème que cite Florenth ???

Et le bouton Tsunami fonctionne ???

Par contre au niveau perte de mémoire ... Aïe aïe aïe ;)

Unexpected Memory Leak
---------------------------
An unexpected memory leak has occurred. The unexpected small block leaks are:



21 - 28 bytes: TBrush x 1, TPen x 1

29 - 36 bytes: TFont x 1, Unknown x 2

53 - 60 bytes: TBitmap x 2

61 - 68 bytes: Unknown x 1

93 - 100 bytes: TBitmapCanvas x 1

109 - 116 bytes: TBitmapImage x 2


---------------------------
OK
---------------------------

Il faut penser à liberer les objets :)

Sinon l'effet est joli ... Bravo
Je regarderai le code de plus près dès que possible.

@+
Cirec
Salut,

J'ai une erreur de vérification d'étendue au niveau de l'utilisation du array[0..0]. Je pense sincèrement que ce genre de "bidouille" bien qu'utilisé aussi par borland, ne soit pas une solution durable.

Je ne peux pas t'en dire plus sur l'erreur, désolé, car tout Delphi a planté après.

++
Rejoignez-nous