Thread et bitmap (dessin au crayon)

Soyez le premier à donner votre avis sur cette source.

Vue 7 971 fois - Téléchargée 681 fois

Description

Suite à un échange sur le forum, je met en ligne un petit programme qui traite une image avec une sorte d'effet de crayon de couleur.
L'effet est quelconque, mais le but n'est pas là.
C'est surtout de faire un thread, pour ce traitement un peu long, et d'affiche le résultat.
Mon problème, c'est l'utilisation des Lock et Unlock, qui me semble de trop, mais qui doivent être présent car, sinon, ça marche pô...

J'ai par ailleurs fait en sorte que le thread s'arrête et recommence dès qu'un paramètre de dessin est modifier.
Et, en plus, une bar de progression pour visualiser le traitement en cours.

Autre petit point pour comprendre la source, je détruis et recrée le thread dès qu'une nouvelle image est ouverte.

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

Messages postés
600
Date d'inscription
samedi 8 juin 2002
Statut
Membre
Dernière intervention
6 avril 2010
1
J'ai oublié une ligne plus haut:

procedure TForm1.FormClose;
begin
NeedUpdate:=False;
MyThread.Terminate;
Event.SetEvent;
MyThread.WaitFor;
FreeAndNil(MyThread);
end;
Messages postés
600
Date d'inscription
samedi 8 juin 2002
Statut
Membre
Dernière intervention
6 avril 2010
1
Pour mettre un thread en standby généralement on utilise un TEvent. Exemple "caricatural":

var
Event:TEvent;
NeedUpdate:Boolean;
MyThread:TMyThread;

procedure TForm1.FormCreate;
begin
Event:=TEvent.Create(nil,False,False,'');
MyThread:=TMyThread.Create;
end;

procedure TForm1.ScrollBar1Change(Sender: TObject);
begin
NeedUpdate:=True;
Event.SetEvent;
end;

procedure TForm1.FormClose;
begin
NeedUpdate:=False;
Event.SetEvent;
MyThread.WaitFor;
FreeAndNil(MyThread);
end;

procedure TMyThread.Execute;
begin
while not Terminated do begin
Event.WaitFor(INFINITE);
if NeedUpdate then begin
NeedUpdate:=False;
ProcessData;
end;
end;
end;
Messages postés
243
Date d'inscription
lundi 30 octobre 2000
Statut
Membre
Dernière intervention
15 juillet 2013

Bon, merci bien pour ces pistes mais une question me viens.

Dans mon cas, comment faire en sorte que le thread s'arrête et affiche le résultat OU annule le traitement et recommence avec de nouvelles valeurs. Dans mon cas, il tourne en boucle, mais est-il possible de mettre le thread en standby une fois terminé OU le forcé à s'arrêter pour le redémarrer tout de suite.

En clair, dans mon évenement OnChange de ma scollbar, il y a deux cas :
1 - mon thread est en plein calcul, il faut le stopper et le relancer
2 - mon thread est en standby, il faut juste le redémarrer

Autre question, si mon thread sort de la fonction Execute, il suffit de faire un RESUME pour relancer cette fonction ou il y a autre chose à faire...

Bien sur, en fonction de toutes ces réponses, je metterai en ligne la version modifier et "optimum"

Barbichette
Messages postés
2527
Date d'inscription
jeudi 15 janvier 2004
Statut
Membre
Dernière intervention
16 octobre 2019
13
Salut,

Hélas, je n'ai pas le temps d'approfondir pour le moment. :s
Mais il me semble bien que si tu regardais vers l'événement OnTerminate du thread, tu y trouverais ton bonheur, Barbichette.

Je ferais une petite démo sur la synchro Thread-secondaire/Thread-principal et Thread-secondaire/thread-secondaire dès que j'aurais un peu plus de temps.
Le sujet est vaste. Et qu'il s'agisse de Canvas ou d'autre chose n'a pas beaucoup d'importance de toute façon.

Cirec et Forman ont raison : c'est un problème de Thread, pas de bitmap dans ton cas.
Lock/Unlock, c'est qu'une section critique et ça ne devrait être réservé qu'à la synchro de 2 Threads secondaires selon moi. Entre le Thread principal et 1 thread secondaire il faut faire plus simple. Et, de façon générale, la synchronisation n'a d'intérêt que quand il y a possibilité de conflit. Ce qui n'est pas le cas dans ton code à première vue.

Autre chose :
Forman écrit « si tu dessines un Bitmap qui est en train d'être modifié dans un autre thread, sans ces sections critiques tu vas afficher le bitmap qui est en cours de traitement, donc incomplet »

Mais c'est beaucoup plus grave que ça !
Imaginons le traitement suivant dans le 1er Thread :

If PixelColor <> 0 then begin
X := Y/PixelColor;
end;

Et dans le 2ème thread :
...
PixelColor := 0;
...

Dans le cas du multi-threading, il peut très bien arrivé que le Scheduler de Windows interrompe le 1er Thread entre la 1ère et la 2ème ligne... Puis donne la main au second Thread, et enfin revienne au 1er.
Là, c'est une belle division par zéro !
Et bonjour pour débuger ce genre d'erreur.
Donc, 'faut toujours prendre énormément de précautions avec les threads.

Encore autre chose :
le multi-threading, c'est bien pour simuler un semblant de pc multi-tâche. Mais, de nos jours, il y a de plus en plus de pc MultiCore. Il faut donc coder pour que, par exemple, ton traitement d'image se fasse sur un processeur dédié et ne pas laisser à la fantaisie de Windows de jongler avec tout ça.
Imagine ton application qui tourne sur un core et ton traitement d'image sur un autre. Là, ça devient un vrai traitement parallèle avec tous les bénéfices en terme de temps de traitement!
On se rapproche là du cerveau humain, de l'inconscient, etc...
'tain! Y'a encore de quoi faire, et j'ai l'impression que ma vie sera trop courte... :'(

Enfin, content d'avoir pu rencontrer mes bons amis ! :)))
Et j'espère pouvoir revenir bientôt sur ce site (s'il ne sombre pas dans la médiocrité de ceux qui n'y voient qu'un outil).
Messages postés
600
Date d'inscription
samedi 8 juin 2002
Statut
Membre
Dernière intervention
6 avril 2010
1
Une bonne idée pour ce genre de traitement ça peut être aussi de travailler sur un DIBSections, c'est un analogue GDI du HBITMAP "device dependant" usuel, sauf que là on a accès directement aux données du bitmap, sous la forme d'un tableau de RGBQuad par exemple. Du coup, en modifiant directement cette mémoire (sans avoir à passer par scanline) on modifie le bitmap sous-jacent de manière très rapide, et en plus on peut dessiner dessus de manière classique avec les fonctions GDI. Il faut éventuellement rajouter une section critique pour les accès concurrents, ainsi que GDIFlush() pour s'assurer que les traitements GDI sont bien finis avant de lire/écrire directement dans la mémoire.

Mais comme tu le dis Cirec, l'architecture des threads (oserais-je dire le tissage) passe avant tout et doit être rigoureusement pensée pour éviter au maximum d'avoir à verrouiller des ressources.
Afficher les 14 commentaires

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.