Performances : trouver où ça freine [Résolu]

Messages postés
511
Date d'inscription
mercredi 4 août 2010
Statut
Membre
Dernière intervention
19 juillet 2019
- - Dernière réponse : Herve_be
Messages postés
511
Date d'inscription
mercredi 4 août 2010
Statut
Membre
Dernière intervention
19 juillet 2019
- 19 juil. 2019 à 17:53
Bonjour,
Je constate qu'un de mes programmes en VB6 est particulièrement lent.
J'ai bien essayé de mettre des GetTickCount() mais le programme est un peu complexe avec des boucles Do/Loop et des For/next imbriqués ainsi que l'appel à de nombreuses sub : difficile d'exploiter les résultats.
Existerait-il un outil ou une méthode permettant de tracer l'exécution pour voir où il passe le plus de temps ?
Merci d'avance pour vos réponses
Afficher la suite 

9 réponses

Meilleure réponse
Messages postés
511
Date d'inscription
mercredi 4 août 2010
Statut
Membre
Dernière intervention
19 juillet 2019
2
1
Merci
J'ai trouvé un autre moyen que PtInRegion pour savoir si un point se trouve dans un polygone :
on calcule la somme des angles entre le point en question et chaque sommet
si le point se trouve dans le polygone la somme = ±Pi sinon elle est nulle

je ne gagne cependant pratiquement rien :
pour le calcul complet avec PtInRegion = 21891 ms, avec le calcul de l'angle = 21516 ms.

Que veux-tu dire par "arithmétique des pointeurs" et "Le calcul de factoriel" ?

Comment pourrai-je faire 3 tableaux ?
J'utilise la fonction GDI GetBitmapBits pour le remplir; il faudrait que je le copie dans 3 tableaux à 2 dimensions pour le traiter puis le recopier dans un tableau à 3 dimensions pour que la fonction GDI SetBitmapBits le retransforme en image.

Dire « Merci » 1

Heureux de vous avoir aidé ! Vous nous appréciez ? Donnez votre avis sur nous ! Evaluez CodeS-SourceS

Codes Sources 123 internautes nous ont dit merci ce mois-ci

denisbertin
Messages postés
194
Date d'inscription
lundi 22 avril 2013
Statut
Membre
Dernière intervention
16 juillet 2019
1 -
Merci, pour cette nouvelle méthode de détermination d'un point à l'intérieur d'un polygone, je ne l'a connaissait pas celle la ! d'ou nous tire-tu cela ? d'autre part il te reste peut-être à essayer un traitement multi-threader, avec tes deux boucles for x et for y si tu as bien un microprocesseur multi-coeur, tu peut essayer, mais je ne pourrais pas te dire comment faire en Basic, parce que ce n'est pas le langage que j'utilise, il te suffirait de créer 4 threads (par exemple) avec une fraction pour chaque boucle for x qui bien sûr encapsulerais aussi la boucle for y. (suggestion).
denisbertin
Messages postés
194
Date d'inscription
lundi 22 avril 2013
Statut
Membre
Dernière intervention
16 juillet 2019
1 -
Un tableau en mémoire vive est déterminer par une adresse en mémoire dans le langage pascal - delphi tu peut obtenir p=@tableau (p l'adresse du tableau en mémoire mais je ne sais pas ssi on peut le faire en basic, pour accéder à l'élément suivant plutôt que de tout recalculer, il suffit d'incrémenter P de la taille (sizeof) de l'élément.

https://fr.wikipedia.org/wiki/Pointeur_(programmation)#Arithm%C3%A9tique_des_pointeurs
Commenter la réponse de Herve_be
Messages postés
511
Date d'inscription
mercredi 4 août 2010
Statut
Membre
Dernière intervention
19 juillet 2019
2
1
Merci
Bonjour,
J'ai essayé une autre méthode que PtInRegion pour savoir si un point se trouve dans le polygone en comptant le nombre d'intersections d'un segment partant du point vers la droite avec les côtés : je ne gagne rien.
Il semble donc que la perte de temps se trouve bien dans l'accès de l'array mais je ne vois vraiment pas comment la diminuer.

Dire « Merci » 1

Heureux de vous avoir aidé ! Vous nous appréciez ? Donnez votre avis sur nous ! Evaluez CodeS-SourceS

Codes Sources 123 internautes nous ont dit merci ce mois-ci

denisbertin
Messages postés
194
Date d'inscription
lundi 22 avril 2013
Statut
Membre
Dernière intervention
16 juillet 2019
1 -
Comme tu as du te rendre compte en supprimant le test de détection pour savoir si un point est bien à l'intérieur de ton polygone, le temps d'exécution était véritablement
beaucoup plus rapide, donc le temps perdu est bien dans cette fonction !
JeuDuTaquin
Messages postés
40
Date d'inscription
mardi 4 juillet 2017
Statut
Membre
Dernière intervention
19 juillet 2019
-
Salut Hervé,
Pour réduire la taille de l'image, tu dois utiliser un autre format BM (1bit, 8bits ou 32bits).
Je ne voie pas de solutions simple, à part passer le RVBc 32bits en tableau 256 couleurs…
Le mieux est de la convertir en niveau de gris, et de traiter un masque en gris sur la transparence de chaque couches ou sur l'ensemble des couches avec le même masque.
Le calcul des masques sera plus rapide, et l'application des masques peuvent se faire en GDI, tout aussi rapidement.
Mais, avec les tests que j'ai fait, le gain n'est pas important sur les trois couches, donc on risque de perdre le temps gagné en recalculs, pré-traitement et post-traitement. Donc, j'y crois pas trop.

@denisbertin : Si c'est une fonction de traitement d'objet, la recoder ne servira à rien!
Il vaut mieux compiler le programmes sans "tester les variables" et utiliser options "brute" d'optimisation d'accès aux variables.

Nota:^pour Hervé : retire les "Debug.print" en mode "débogage", ça vas plus vite !
;)
denisbertin
Messages postés
194
Date d'inscription
lundi 22 avril 2013
Statut
Membre
Dernière intervention
16 juillet 2019
1 -
Si tu veux vraiment savoir si un pixel est situé dans un polygone de façon très très rapide, créer un bitmap de la taille (surface) de ton polygone, ce bitmap doit avoir un fond blanc (par exemple) dessine ton polygone avec une couleur bleu (différente du blanc), parcours dans deux boucles X et Y ce bitmap à chaque fois que ce pixel est bleu tu es à l'intérieur du polygone ! la méthode la plus rapide.... ton bitmap peut être monochrome (seulement noir ou blanc) pour être encore plus efficace.
Commenter la réponse de Herve_be
Messages postés
40
Date d'inscription
mardi 4 juillet 2017
Statut
Membre
Dernière intervention
19 juillet 2019
0
Merci
Salut Hervé,

La programmation sur le vb5 ou 6 est une philosophie…
Tu peux gagner du temps d'execution sur les options de compilation, en retirant toutes les vérifications de variables…

Mais, un bon code est un code optimisé.
Oublie les fonctions chronophages du basic, et pense C# !
N'utilise plus de chaînes, mais des tableaux en BYTES…

Déclare chaque valeur en LOCAL et réduis les longueurs de chaînes.
Quite a effacer les données traitées.

Il y a plein d'astuces pour "booster" les traitements… mais, la plupart du temps, c'est un problème lié à la lourdeur de la gestion des variables.

Et à force de répétitions, ces latences systèmes te font perdre un temps énorme en fin de boucle.

Donc, STRING en BYTES() puis BYTES() en STRING.
Travail sur des variables de taille réduite en string, ou sur une copie qui sera tronquée.

Utilisation des API comme Copymemory sur les bytes et STRING.
Le temps gagné est non négligeable.
JeuDuTaquin
Messages postés
40
Date d'inscription
mardi 4 juillet 2017
Statut
Membre
Dernière intervention
19 juillet 2019
-
Ha, oui !
évite les sub/fonctions trop nombreuses dans les boucles si elle ne sont pas justifiées.
Mieux vaut réécrire un petit morceau de code, que de forcer le code à jumper sur une routine en PUBLIC qui aura à transférer les infos à chaque fois.
Limite le nombre de ligne et utilise IIF(x,x,x) au lieu des IFs…
JeuDuTaquin
Messages postés
40
Date d'inscription
mardi 4 juillet 2017
Statut
Membre
Dernière intervention
19 juillet 2019
-
Le secret est de limiter le nombre de lignes, et de tests inutiles…

IF a$="a" then …
IF a$="b" then …


Est a proscrire.
Utiliser:

DIM a as string*1

Select Case cbyte(a)

Case &H0
StrText = "NOP"


Ne pas hésiter à faire des tests élargis avec des GOTOs pour éviter les tests inutiles et chronophages. Pareil pour les SUB et les fonctions (sortie avec des Exit Sub ou Exit Function) avant la fin de la sub ou de la fonction.
denisbertin
Messages postés
194
Date d'inscription
lundi 22 avril 2013
Statut
Membre
Dernière intervention
16 juillet 2019
1 -
Monsieur Niklaus Wirth qui a élaboré le langage de programmation Pascal pensé dans son langage de prédilection que tous les Goto pouvais être éliminé, ce n'était pas le cas, car même quand dans un test if then else ce compilateur produisait des jump to une adresse en assembleur une fois compilé, cependant sa formulation exact était correct, dans mon programme logiciel écrit dans ce langage je me suis bien sur amuser à exclure tous les sots en mémoire comme ont pourrais le faire avec un @label. et de vérifier ces propositions. Bien sûr les nombreuses répétitions du même test comme dans l'exemple "Une couleur au hasard avec choix de la couleur et du ton" peuvent être évitée car elle forme des redondances inutile.

https://fr.wikipedia.org/wiki/Niklaus_Wirth
Commenter la réponse de JeuDuTaquin
Messages postés
194
Date d'inscription
lundi 22 avril 2013
Statut
Membre
Dernière intervention
16 juillet 2019
1
0
Merci
La fonction GetTickCount() permet d'obtenir le temps en milliseconde de la valeur de ce compteur de temps et ne permet pas d’optimiser ton programme mais de mesurer sa période en milliseconde, tu va alors recevoir une valeur que tu peut comparer avec le GetTickCount() en sortie de ton module, avec la différence entre ces deux valeurs qui permet d'obtenir le temps de latence ou d’exécution de ce module time actuel - time_before; en milliseconde, Si tu veux aussi comprendre la somme des instructions d'un module est égal à la somme des instructions qui le compose. si tu effectue des boucles for i = n to m, toutes les variables qui ne sont pas une fonction de i peuvent être écrite en aval de cette boucle et prédéterminées à l'avance, la fonction call to subroutine empile dans le stack segment (le segment de pile) tous les paramètres de cette fonction soit n paramètre(n) et une fonction, si tu veux éviter cette accumulation ton code deviendras plus illisible mais peut-être qu'il fonctionneras un peut plus rapidement du fait de la linéarisation de ton code sans différer, en définitive tous le monde devrait commencer par apprendre le langage assembleur des microprocesseurs pour savoir ce qu'il font vraiment, denis.
Commenter la réponse de denisbertin
Messages postés
511
Date d'inscription
mercredi 4 août 2010
Statut
Membre
Dernière intervention
19 juillet 2019
2
0
Merci
Bonjour et merci pour vos réponses (je n'ai pas reçu de notification).
J'ai trouvé un outil d'analyse : VB Watch.
L'essentiel du temps est passé dans une boucle (2 for/next imbriqués) qui sert à modifier une image bitmap : je copie l'image dans un array et j'y dessine un polygone transparent,
Opacité est celle du polygone à dessiner, transparence celle de ce qu'il y a en dessous
CC1, 2 et 3 sont les 3 couleurs RGB du polygone à dessiner
voici le code
Dim rgn  As Long  '  région
Dim Xleft As Integer
Dim Xright As Integer
Dim X As Integer
Dim Y As Integer
Dim Ybottom As Integer
Dim Transparence As Single
Dim Opacite As Single
Dim fx As Single
Dim fy As Single

rgn = CreatePolygonRgn(Vertices(0), Vertex, Winding)
Call GetObject(Graph(n).Image, Len(PicInfo), PicInfo)
ReDim ImageArray(3, (PicInfo.bmWidth - 1), (PicInfo.bmHeight - 1)) As Byte
Noctets = PicInfo.bmWidth * PicInfo.bmHeight * 4
Call GetBitmapBits(Graph(n).Image, Noctets, ImageArray(0, 0, 0)) ' Copie image dans array
For X = Xleft To Xright        ' Abscisses min et max du polygone à dessiner
        For Y = Y1 To Ybottom        ' Ordonnées min et max du polygone à dessiner
                If PtInRegion(rgn, X, Y) <> 0 Then
                        Transparence = 1 - Opacite       
                         ImageArray(0, X, Y) = (ImageArray(0, X, Y) * Transparence) + (CC3 * Opacite)
                         ImageArray(1, X, Y) = (ImageArray(1, X, Y) * Transparence) + (CC2 * Opacite)
                         ImageArray(2, X, Y) = (ImageArray(2, X, Y) * Transparence) + (CC1 * Opacite)
                 End If
         Next Y
Next X
Call SetBitmapBits(Graph(n).Image, Noctets, ImageArray(0, 0, 0)) ' Copie array dans image
Call DeleteObject(rgn)
Ce qui prend le plus de temps est (3 fois)
ImageArray(0, X, Y) = (ImageArray(0, X, Y) * Transparence) + (CC3 * Opacite)
comment pensez-vous que je pourrais accélérer ?
pascal16m
Messages postés
67
Date d'inscription
jeudi 19 juin 2003
Statut
Membre
Dernière intervention
13 juillet 2019
-
faire ImageArray(0, X, Y) puis ImageArray(1, X, Y) provoque un grand saut en mémoire qui est recalculé à chaque fois donc lent en accès.

essaies de séparer en 3 boucles
une boucle qu'avec des ImageArray(0, X, Y)
une boucle qu'avec des ImageArray(1 X, Y)
une boucle qu'avec des ImageArray(2, X, Y)
Y étant la dernière dimension du tableau, X et Y sont appelés dans le bon ordre

CCx * Opacite est-il constant ? si oui, sort-le de la boucle et crées une variable qui contient cette valeur une fois pour toute.

ensuite tu ré-affectes la valeur au même tableau, vu qu'on ne peux pas lire et écrire une valeur en même temps, il y a des latences rajoutée (les optimisations qui permettent de faire plusieurs opérations en 1 cycle d'horloge ne se font pas). Tu peux envoyer tes valeurs dans un second tableau, ça perd de la ram, mais ça a de grandes chances d'aller plus vite.

si tu peux faire du multi thread (je sais pas en vb6). tu peux extraire 3 sous tableaux 0, 1 et 2, et tu lances 3 calculs en parallèle, que tu assembles ensuite.
Comme les appels sont indépendants, tu n'auras pas de blocage ou ralentissement inter thread
Commenter la réponse de Herve_be
Messages postés
511
Date d'inscription
mercredi 4 août 2010
Statut
Membre
Dernière intervention
19 juillet 2019
2
0
Merci
Merci pour ta réponse,
Le polygone représente un faisceau lumineux de moins en moins intense au fur et à mesure qu'on s'éloigne de la source; par conséquent "Opacite" n'est pas constant, il est recalculé pour chaque combinaison X,Y.
Par conséquent si je fais 3 boucles ImageArray(0/1/2 je gagnerai en accès au tableau mais je devrai recalculer Opacite 3 fois plus souvent, pas sur au final que j'y gagne qqch.

Par contre lire un array et écrire dans un autre c'est facile, j'ai de suite essayé.
Bizarrement je ne gagne rien : une boucle dure toujours 235 ms !
denisbertin
Messages postés
194
Date d'inscription
lundi 22 avril 2013
Statut
Membre
Dernière intervention
16 juillet 2019
1 -
C'est certainement la fonction PtInRegion qui est trop lente.
Commenter la réponse de Herve_be
Messages postés
511
Date d'inscription
mercredi 4 août 2010
Statut
Membre
Dernière intervention
19 juillet 2019
2
0
Merci
J'ai essayé avec une opacité fixe de faire 3 boucles : surprise, c'est encore plus lent.
La raison est en effet que je dois appeler PtInRegion 3 fois plus souvent.
J'ai supprimé cet appel; évidemment ça ne fonctionne plus parce qu'il altère tous les pixels et pas uniquement ceux situés dans la région mais c'est beaucoup plus rapide.

N'y a-t-il pas moyen de trouver une fonction plus performante pour vérifier si un pixel est bien dans le polygone ?
denisbertin
Messages postés
194
Date d'inscription
lundi 22 avril 2013
Statut
Membre
Dernière intervention
16 juillet 2019
1 -
Pour cela dessiner un polygone quelconque (concave ou convexe) sur une feuille de papier, se munir d'un stylo à bille bleu (la couleur est indifférente), placer son doigt au sommet de ce stylo, puis lui donner un mouvement longitudinale, compter le nombre d'intersection ?
denisbertin
Messages postés
194
Date d'inscription
lundi 22 avril 2013
Statut
Membre
Dernière intervention
16 juillet 2019
1 -
Si tu veux comprendre un traitement multi-threader pour le répartir sur de nombreux cœur de calcul, dans mon langage de prédilection comme je l'ai formulé tu peut observer ce code source, que j'ai publié à l'intention des internautes et des membres de code source, comment ça marche :

https://codes-sources.commentcamarche.net/source/55268-caculer-une-factorielle-avec-plusieurs-coeur-de-calcul-et-afficher-les-temps-d-executions
denisbertin
Messages postés
194
Date d'inscription
lundi 22 avril 2013
Statut
Membre
Dernière intervention
16 juillet 2019
1 -
Si tu veux connaître une autre optimisation possible quand tu accède à un tableau à trois dimensions, soit P l'adresse de départ de ton tableau en mémoire, alors si ce tableau est composé de N dimensions, alors l'adresse de P(x,y) est égal à P + X + Y multiplier par la largeur du tableau en deux dimensions quand tu adresse un élément de ce tableau pour multiplier sa valeur par un coefficient de transparence dans ton calcul tu effectue deux fois cette opération pour adresser l'élément p(i,j) or une seule adresse en mémoire correspond à ce calcul, mais tu effectue sur trois dimensions ces même opération : ImageArray(0, X, Y) = (ImageArray(0, X, Y) * Transparence) + (CC3 * Opacite), tu peut te rendre compte que l'adresse en mémoire de ImageArray(0, X, Y) est égale mais tu effectue deux fois ce calcul, l'arithmétique des pointeurs te permettrais de la faire une seule fois.
denisbertin
Messages postés
194
Date d'inscription
lundi 22 avril 2013
Statut
Membre
Dernière intervention
16 juillet 2019
1 -
Le calcul de factoriel en trois caractères a=1; for i =1 to n do a=a*i; result a;
Salut,
Je ferai trois tableaux en RG & B, ça divise la variable par 3 pour ton "ImageArray", et le cumul du temps de traitement te donnera un traitement plus d'informations élevé… pris séparément.
Commenter la réponse de Herve_be
Messages postés
511
Date d'inscription
mercredi 4 août 2010
Statut
Membre
Dernière intervention
19 juillet 2019
2
0
Merci
@denisbertin Que veux-tu dire par "arithmétique des pointeurs" et "Le calcul de factoriel" ?

@jeudutaquin Comment pourrai-je faire 3 tableaux ?
J'utilise la fonction GDI GetBitmapBits pour le remplir; il faudrait que je le copie dans 3 tableaux à 2 dimensions pour le traiter puis le recopier dans un tableau à 3 dimensions pour que la fonction GDI SetBitmapBits le retransforme en image.
JeuDuTaquin
Messages postés
40
Date d'inscription
mardi 4 juillet 2017
Statut
Membre
Dernière intervention
19 juillet 2019
-
Salut,

Tu dois imaginer le traitement des variables en VB6 comme un process linéaire à accès séquentiel.
En gros, la valeur x,y est recherchée pas sauts de valeurs.
Donc, plus le tableau est grand, plus il mettra de temps à traiter l'accès aux informations.

Tu dois dans le cas d'un fichier ou variable de grande taille, le 'streamer' par fragmentations pour en réduire la taille.
Le temps d'accès s'en trouve réduit pour l'ensemble du traitement.
Tu prends ton tableau en 3 niveaux, et tu le sépare en 3 tableau de 2 dimensions.

DATA (Niveau 0:Data (x,y),Niveau 1:Data (x,y),Niveau 2:Data (x,y))

DATA Niveau 0: Data (x,y)
DATA Niveau 1: Data (x,y)
DATA Niveau 2: Data (x,y)

Pour cela, il te faut utiliser la fonction COPYMEMORY (en Bytes<>Bytes) et le pointeur mémoire VarPtr()
Dans le cas d'une variables à plusieurs niveaux, il faut connaitre la structure d'encombrement mémoire de cette variable!
Généralement stockée par bloc, il te faut copier ces blocs de manière précautionneuse, car le COPYMEMORY peut créer des débordements et des effacements de d'informations les variables stockées en mémoire.
Mais, si le COPYMEMORY est bien cadré, le process est sûre et rapide.

Il faut faire des tests pour voir si il est possible d’établir une réversibilité vers la variable en 3 dimension avec la même technique.

Et je pense que @denisbertin te suggère de linéariser ton tableau 2 dimensions en en tableau simple où ton point se trouve en (y*width)+x, ce qui doit aussi éviter des cycles de scrutation mémoire.
JeuDuTaquin
Messages postés
40
Date d'inscription
mardi 4 juillet 2017
Statut
Membre
Dernière intervention
19 juillet 2019
-
Salut,
Après avoir testé un code de dissection d'une variable de 3 vers 2 dimensions…
Le traitement est plus rapide… mais corrompu.
Sub Test3()
Dim x, y As Integer
Dim Image0(3000, 3000) As Byte
Dim Image1(3000, 3000) As Byte
Dim Image2(3000, 3000) As Byte

CopyMemoryByte Image0(0, 0), Image3D(0, 0, 0), 3000 + 1
CopyMemoryByte Image1(0, 0), Image3D(1, 0, 0), 3000 + 1
CopyMemoryByte Image2(0, 0), Image3D(2, 0, 0), 3000 + 1

For x = 0 To 3000
For y = 0 To 3000
Image0(x, y) = (x + y) And 255
Image1(x, y) = (x + y) And 255
Image2(x, y) = (x + y) And 255
Next y, x

CopyMemoryByte Image3D(0, 0, 0), Image0(0, 0), 3000 + 1
CopyMemoryByte Image3D(1, 0, 0), Image1(0, 0), 3000 + 1
CopyMemoryByte Image3D(2, 0, 0), Image2(0, 0), 3000 + 1

End Sub

Car les niveaux sont indexés ainsi:
DIM a(x)= 1234567
DIM a(x,y)=11223344556677
DIM a(x,y,z)=111222333444555666777
Et copymemory est bêtement linéaire… donc, il efface tout.
La seule solution est de créer un fichier temporaire et d'y PUT#er les valeurs les unes après les autres et de faire un GET# de la variables en 3 niveaux.
Ce qui est beaucoup plus long.
On peut tout mettre dans un tableau simple de longueur 3 fois plus grande en X,X+1 et X+2... mais, on ne gagne plus rien en rapidité… et c'est même pire.
Par contre, pour annoncer une bonne nouvelle (au moins une), ton choix de For-next est le bon… DO-loop est plus lent de pas grand chose, mais bon…

Pour les réponses de @denisbertin, je suis un peu perdu!
Il faut garder en mémoire que nous somme sur du VB6, programmé pour le Windows 95 … multi-tâches en win32... mais que la notion de "simultanéité", "multi-cores" et "multi-procès" … étaient de la science fiction à celle époque. Même si les DLLs et les routines sont supportées, il faut rester humble face aux possibilités d'un logiciel qui a survécu au bug de l'an 2000. Oui, une DLL en assembleur serai la solution, mais autant changer de language dans ce cas.

Donc, l'accélération ne peut être que dans la forme et non le fond.
JeuDuTaquin
Messages postés
40
Date d'inscription
mardi 4 juillet 2017
Statut
Membre
Dernière intervention
19 juillet 2019
> JeuDuTaquin
Messages postés
40
Date d'inscription
mardi 4 juillet 2017
Statut
Membre
Dernière intervention
19 juillet 2019
-
Pas de gain en rapidité… tableau trop grand.
Private Declare Sub CopyMemoryByte Lib "kernel32" Alias "RtlMoveMemory" (lpvDest As Any, lpvSource As Any, ByVal cbCopy As Long)
Dim Image3D(2, 3000, 3000) As Byte
'-------------------------------------

Erase Image3D
Dim Image4((3001 ^ 2 * 3) - 1) As Byte ' image(2,3000,3000)=>3*3000*3000=3000^2*3
For x = 0 To ((3001 ^ 2 * 3) - 1) Step 3
Image4(x) = (x) And 255 ' tableau 1: image(0,x,x)
Image4(x + 1) = (x) And 255 ' tableau 2: image(1,x,x)
Image4(x + 2) = (x) And 255 ' tableau 3: image(2,x,x)
Next x

CopyMemoryByte Image3D(0, 0, 0), Image4(0), (3001 ^ 2 * 3) + 1

Commenter la réponse de Herve_be
Messages postés
511
Date d'inscription
mercredi 4 août 2010
Statut
Membre
Dernière intervention
19 juillet 2019
2
0
Merci
J'ai finalement trouvé une solution très rapide : Alphablend.
Je mélange l'image ci-dessous avec l'image déjà créée en délimitant le contour avec un array de sommets.
Merci pour votre aide, problème résolu

Commenter la réponse de Herve_be