COMMENT OPTIMISER LES TIMAGE (GAIN DE TEMPS ET DE CALCUL IMPORTANT)

Messages postés
756
Date d'inscription
vendredi 21 mars 2003
Statut
Membre
Dernière intervention
1 octobre 2009
- - Dernière réponse : cs_grandvizir
Messages postés
1237
Date d'inscription
samedi 8 novembre 2003
Statut
Membre
Dernière intervention
3 septembre 2006
- 27 juil. 2004 à 19:47
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/24123-comment-optimiser-les-timage-gain-de-temps-et-de-calcul-important

Afficher la suite 
cs_grandvizir
Messages postés
1237
Date d'inscription
samedi 8 novembre 2003
Statut
Membre
Dernière intervention
3 septembre 2006
10 -
J'ai tout plein de réponses qui vont mettre un terme à tous ces dialogues réfléchis et aux bidouillages grotesques proposés (désolé, mais c'est ça).

>>>>>>>>>

En effet, rappatrier ExtCtrls est ridicule, car on en a déjà un et il suffit de modifier ce qu'il nous propose. Comment aurais-tu fait si t'avais pas eu le code source?? Proprement, tu aurais simplement écrit une ligne de code très simple:

procedure TForm1.FormCreate(Sender:TObject);
begin
Image1.Picture.OnChange:=nil;
end;

>>>>>>>>>

Quand t'utilises Image1.Canvas.Pixels[X,Y]:=clRed; voilà ce qui se passe en arrière-plan:

procedure TCanvas.SetPixel(X,Y:Integer; Value:TColor);
begin
Changing;
RequiredState([csHandleValid, csPenValid]);
Windows.SetPixel(FHandle, X, Y, ColorToRGB(Value));
Changed;
end;

Là, on voit que non seulement il y a ralentissement avec Changed qui appelle PictureChanged, mais également avec Changing qui appelle autre chose. On peut illustrer ceci. Teste donc les lignes suivantes. Derriere chaque OnBidule, il se passe quelque chose puisqu'un "1" est affiché dans les 3 cas.
ShowMessage(IntToStr(Ord(Assigned(Image1.Canvas.OnChanging))));
ShowMessage(IntToStr(Ord(Assigned(Image1.Canvas.OnChange))));
ShowMessage(IntToStr(Ord(Assigned(Image1.Picture.OnChange))));

Ainsi, si Canvas.Pixels[x,y]:=Couleur t'embête, alors tu remplaces simplement par:
Windows.SetPixel(Image1.Picture.Bitmap.Canvas.Handle, X, Y, Couleur);

Cette fonction est importée depuis GDI32:
function SetPixel(DC,X,Y,Color:integer):integer; external 'gdi32.dll';

Elle est aussi rapide que le TRGBTripleArray, et est plus claire. Donc...

Si tu regardes dans Windows.pas, tu verras dans l'énoncé de la fonction que Color est un COLORREF. Pas de problèmes: COLORRED=DWORD=integer. Et comme TColor=integer, t'as pas besoin d'utiliser la fonction ColorToRGB: inutile et perte de temps. Enfin, tout dépend de ce que tu veux faire, mais moi je ne l'utiliserai pas.

MAIS ATTENTION!! Cette fonction nécessite que tu ais déjà créé un bitmap dans ton TImage, ce qui n'est pas le cas quand tu places simplement un TImage sur la fenêtre. Il faut mettre un petit code dans l'évènement OnCreate de la fenêtre:

procedure TForm1.FormCreate(Sender:TObject);
begin
Image1.Picture.Bitmap.ReleaseHandle;
with Image1.Picture.Bitmap.Create do
begin
Canvas.Brush.Color:=clWhite;
Canvas.Pen.Color:=clBlack;
Canvas.Pen.Width:=1;
PixelFormat:=pf24bit;
Width:=Image1.Width;
Height:=Image1.Height;
end;
Image1.Refresh;
end;

Au final, ta boucle ressemble à ce qui suit. Et en plus, t'as même plus besoin de te préoccuper de PictureChanged.

procedure TForm1.Button1Click(Sender: TObject);
var x, y : Integer;
begin
for x:=0 to Image1.Width-1 do
for y:=0 to Image1.Height-1 do
Windows.SetPixel(Image1.Picture.Bitmap.Canvas.Handle, X, Y, clRed);
Image1.Refresh;
end;

>>>>>>>>>

Que le Canvas soit caché ou non, ça n'a pas d'importance puisque cela ne réduit pas tous les calculs qui se produisent...

>>>>>>>>> ALORS ?? :)) <<<<<<<<<
cs_jmic
Messages postés
13
Date d'inscription
mardi 26 août 2003
Statut
Membre
Dernière intervention
25 juillet 2006
-
De nouveau moi.

Pour t'aider à comprendre l'utilisation des canvas cachés et des copies d'images (et aussi parce que prendre des idées sur delphifr, c'est bien, mais que l'on peut aussi participer :-), j'ai fait un petit programme montrant leur utilisation. C'est "compte à rebours style film année 60". Si tu as des questions n'hésite pas (mais je pars demain une semaine).
cs_Kenavo
Messages postés
756
Date d'inscription
vendredi 21 mars 2003
Statut
Membre
Dernière intervention
1 octobre 2009
1 -
Le temps de changer un pixel est négligeable, par rapport au temps nécessaire à le localiser.
Si tu veux tracer une simple ligne verticale avec Pixels, tu divise le temps pour remplir toute l'image par le nombre de point en largeur ! (Ca peut faire 1000) ce n'est pas le cas pour ScanLine.
Dans ces cas là, je dirais même que l'essentiel du temps est utilisé à copier le Bitmap temporaire dans l'imge.

Il reste des essais à faire pour quantifier tout ça !

Ken@vo
cs_Zeroc00l
Messages postés
370
Date d'inscription
lundi 1 avril 2002
Statut
Membre
Dernière intervention
11 février 2010
-
jmic :

J'avais deja pensé à utiliser la même méthode que toi.. utiliser un canvas caché maisje n'ais pas trouve comment manipuler un canvas : lui affecter une taille (Width and Height) le transferer "d'un coup" sur le TImage visible etc ...

Kenavo ... OK
J'ai pas encore testé si le fait de faire des changement de range (depointeur donc ) avant de changer un pixel (donc deux truc ) à changer quand je veux changer un pixel contre un avant.
Mais je pense que ca sera également plus rapide...
cs_jmic
Messages postés
13
Date d'inscription
mardi 26 août 2003
Statut
Membre
Dernière intervention
25 juillet 2006
-
Bonjour,
Pour des raisons de rapidité (mais aussi pour d'autres raisons), j'utilise un canvas "masqué", de même taille mais non affiché à l'écran. J'y fais toutes les manipulations que je veux puis je le transfère d'un coup sur le Canvas affiché à l'écran (par la fonction canvas.copyrect () ). Je ne sais pas si, dans le cas qui te préoccupe, cela améliore la vitesse de l'exécution, mais en tous les cas ça évite les problèmes de réaffichage et de clignottement intempestif. Evidemment, ça mange un peu plus de mémoire !