Accélérer la recherche des contours d'une image (ASM ?)

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Octavius
Messages : 312
Inscription : jeu. 26/juil./2007 12:10

Accélérer la recherche des contours d'une image (ASM ?)

Message par Octavius »

Voici le code que j'ai créé pour trouver les pixels qui bordent une région colorée. Ceci n'est qu'un exemple, mais j'ai besoin d'optimiser ce code car dans mon programme (environ 5000 lignes de code...) j'utilise une procédure similaire dans la boucle principale et ça me fait ramer un peu, surtout en mode débogueur. Je n'y connais rien en ASM, mais s'il est possible d'optimiser (déjà bien optimisée pourtant il me semble...) la partie entre les FOR/NEXT je suis prenneur !

Bon sinon ça peut toujours servir d'exemple pour ceux qui cherchent un code de ce genre.

Code : Tout sélectionner


Enumeration
#Img1
#Img2
#Win
#Button
EndEnumeration

;Pour inverser les conventions RGB et BGR
Macro ReverseRGB(COLOR)
  (COLOR & $FF0000) >> 16 + (COLOR & $00FF00) + (COLOR & $0000FF) << 16
EndMacro

;Test si c'est un pixel de bordure
Macro BorderMap(BMP,X,Y)
  X=0 Or X=BMP\bmWidth-1 Or Y=0 Or Y=BMP\bmHeight-1
EndMacro

CreateImage(#Img1,360,240,32)
CreateImage(#Img2,360,240,32)

StartDrawing(ImageOutput(#Img1))
  Box(0,0,360,240,RGB(255,255,255))
  Circle(100,100,40,RGB(255,0,0))
  Circle(130,110,25,RGB(255,0,0))
  Circle(220,120,35,RGB(255,0,0))
  Box(140,100,60,30,RGB(255,0,0))
StopDrawing()

StartDrawing(ImageOutput(#Img2))
  Box(0,0,360,240,RGB(255,255,255))
StopDrawing()

*Address1=AllocateMemory(36)
*Address2=AllocateMemory(36)

Color=RGB(255,0,0)

GetObject_(ImageID(#Img1),SizeOf(BITMAP),@Img1.BITMAP)
GetObject_(ImageID(#Img2),SizeOf(BITMAP),@Img2.BITMAP)

For i=0 To 8 : PokeL(*Address2+i*4,ReverseRGB(Color)) : Next i

;***************************************************************************************
;-Détection des contours

For Y=0 To Img1\bmHeight-1
  For X=0 To Img1\bmWidth-1
    ;Si c'est un pixel de la bonne couleur
    If PeekL(Img1\bmBits+X*4+Y*Img1\bmWidthBytes)=ReverseRGB(Color)
      ;Si c'est un pixel de bordure
      ;Alors c'est un pixel de contour
      If BorderMap(Img1,X,Y)
        PokeL(Img2\bmBits+X*4+Y*Img2\bmWidthBytes,0)
      Else
        ;Si ce N'est PAS un pixel de bordure
        ;On teste les 9 pixels aux alentours
        CopyMemory(Img1\bmBits+(X-1)*4+(Y-1)*Img1\bmWidthBytes,*Address1,12)
        CopyMemory(Img1\bmBits+(X-1)*4+(Y)*Img1\bmWidthBytes,*Address1+12,12)
        CopyMemory(Img1\bmBits+(X-1)*4+(Y+1)*Img1\bmWidthBytes,*Address1+24,12)
        ;Si la couleur des 9 pixels enregistrés n'est pas identique
        ;A la couleur de la région sélectionnée
        ;Alors c'est un pixel de bordure
        If Not CompareMemory(*Address1,*Address2,36)
          PokeL(Img2\bmBits+X*4+Y*Img2\bmWidthBytes,0)
        EndIf
      EndIf
    EndIf
  Next X
Next Y

;***************************************************************************************

OpenWindow(#Win,0,0,360,300,"Fenêtre",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
CreateGadgetList(WindowID(#Win))
ButtonGadget(#Button,150,250,60,40,"Changer")

Contour=0

;-Boucle principale

Repeat

Event=WaitWindowEvent()

Select Event
  Case #PB_Event_CloseWindow
    End
  Case #PB_Event_Gadget
    Event=EventGadget()
    Select Event
      Case #Button
        Contour=1-Contour
    EndSelect
EndSelect

StartDrawing(WindowOutput(#Win))
  If Not Contour
    DrawImage(ImageID(#Img1),0,0)
  Else
    DrawImage(ImageID(#Img2),0,0)
  EndIf
StopDrawing()

ForEver
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Message par djes »

En enlevant 12 multiplications * bmwidth * bmheight, ça devrait être un poil plus rapide ;)

Code : Tout sélectionner

Enumeration
#Img1
#Img2
#Win
#Button
EndEnumeration

;Pour inverser les conventions RGB et BGR
Macro ReverseRGB(COLOR)
  (COLOR & $FF0000) >> 16 + (COLOR & $00FF00) + (COLOR & $0000FF) << 16
EndMacro

;Test si c'est un pixel de bordure
Macro BorderMap(BMP,X,Y)
  X=0 Or X=BMP\bmWidth-1 Or Y=0 Or Y=BMP\bmHeight-1
EndMacro

CreateImage(#Img1,360,240,32)
CreateImage(#Img2,360,240,32)

StartDrawing(ImageOutput(#Img1))
  Box(0,0,360,240,RGB(255,255,255))
  Circle(100,100,40,RGB(255,0,0))
  Circle(130,110,25,RGB(255,0,0))
  Circle(220,120,35,RGB(255,0,0))
  Box(140,100,60,30,RGB(255,0,0))
StopDrawing()

StartDrawing(ImageOutput(#Img2))
  Box(0,0,360,240,RGB(255,255,255))
StopDrawing()

*Address1=AllocateMemory(36)
*Address2=AllocateMemory(36)

Color=RGB(255,0,0)

GetObject_(ImageID(#Img1),SizeOf(BITMAP),@Img1.BITMAP)
GetObject_(ImageID(#Img2),SizeOf(BITMAP),@Img2.BITMAP)

For i=0 To 8 : PokeL(*Address2 + i*4, ReverseRGB(Color)) : Next i

;***************************************************************************************
;-Détection des contours

n.l = ReverseRGB(Color) 

*src.l = Img1\bmBits
*dst.l = Img2\bmBits

For Y = 0 To Img1\bmHeight - 1

  For X = 0 To Img1\bmWidth - 1

    ;Si c'est un pixel de la bonne couleur
    If PeekL(*src) = n

      ;Si c'est un pixel de bordure
      ;Alors c'est un pixel de contour
      If BorderMap(Img1, X, Y)
        PokeL(*dst, 0)
      Else

        ;Si ce N'est PAS un pixel de bordure
        ;On teste les 9 pixels aux alentours
        CopyMemory(*src - 4 - Img1\bmWidthBytes, *Address1,      12)
        CopyMemory(*src - 4                    , *Address1 + 12, 12)
        CopyMemory(*src - 4 + Img1\bmWidthBytes, *Address1 + 24, 12)

        ;Si la couleur des 9 pixels enregistrés n'est pas identique
        ;A la couleur de la région sélectionnée
        ;Alors c'est un pixel de bordure
        If Not CompareMemory(*Address1, *Address2, 36)
          PokeL(*dst, 0)
        EndIf

      EndIf
    EndIf

    *src + 4
    *dst + 4

  Next X

  *src + Img1\bmWidthBytes - (4 * Img1\bmWidth)
  *dst + Img2\bmWidthBytes - (4 * Img2\bmWidth)
  
Next Y

;***************************************************************************************

OpenWindow(#Win,0,0,360,300,"Fenêtre",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
CreateGadgetList(WindowID(#Win))
ButtonGadget(#Button,150,250,60,40,"Changer")

Contour=0

;-Boucle principale

Repeat

Event=WaitWindowEvent()

Select Event
  Case #PB_Event_CloseWindow
    End
  Case #PB_Event_Gadget
    Event=EventGadget()
    Select Event
      Case #Button
        Contour=1-Contour
    EndSelect
EndSelect

StartDrawing(WindowOutput(#Win))
  If Not Contour
    DrawImage(ImageID(#Img1),0,0)
  Else
    DrawImage(ImageID(#Img2),0,0)
  EndIf
StopDrawing()

ForEver
Octavius
Messages : 312
Inscription : jeu. 26/juil./2007 12:10

Message par Octavius »

Merci c'est un peu mieux!

Mais je voudrais continuer à essayer d'optimiser cette procédure, donc je suis toujours preneur si vous avez d'autres codes dans votre besace.
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Message par djes »

Oh et bien oui, il y a plusieurs façons! Déjà éviter le test des bordures dans toute la boucle (qui ne sert à rien, puisque tu sais les dimensions de l'image). Ensuite éviter les copymemory et compare qui je pense pour 9 données sont trop gourmands; enfin voir si tu ne peux pas verrouiller la zone mémoire pour un accès plus rapide. Moins il y aura d'instructions plus ce sera rapide!
Octavius
Messages : 312
Inscription : jeu. 26/juil./2007 12:10

Message par Octavius »

djes a écrit :Déjà éviter le test des bordures dans toute la boucle (qui ne sert à rien, puisque tu sais les dimensions de l'image).
Oui ça je dois pouvoir me débrouiller je pense, bonne idée.
djes a écrit :Ensuite éviter les copymemory et compare qui je pense pour 9 données sont trop gourmands;
Par quoi les remplacer ? C'est beaucoup plus rapide que si je teste individuellement la couleur des neuf pixels...
djes a écrit :enfin voir si tu ne peux pas verrouiller la zone mémoire pour un accès plus rapide. Moins il y aura d'instructions plus ce sera rapide!
Comment on fait pour verrouiller une zone mémoire ?

PS: Le système des deux boucles imbriquées FOR/NEXT est-il gourmand ? Y a-t-il un moyen plus rapide de procéder ?
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Message par djes »

Octavius a écrit :
djes a écrit :Déjà éviter le test des bordures dans toute la boucle (qui ne sert à rien, puisque tu sais les dimensions de l'image).
Oui ça je dois pouvoir me débrouiller je pense, bonne idée.
djes a écrit :Ensuite éviter les copymemory et compare qui je pense pour 9 données sont trop gourmands;
Par quoi les remplacer ? C'est beaucoup plus rapide que si je teste individuellement la couleur des neuf pixels...
djes a écrit :enfin voir si tu ne peux pas verrouiller la zone mémoire pour un accès plus rapide. Moins il y aura d'instructions plus ce sera rapide!
Comment on fait pour verrouiller une zone mémoire ?

PS: Le système des deux boucles imbriquées FOR/NEXT est-il gourmand ? Y a-t-il un moyen plus rapide de procéder ?
Je vais essayer de te bidouiller un truc. Il faudrait d'abord voir s'il n'y a pas un algo plus rapide. Pour les for/next, le gain serait négligeable même si la mémoire était linéarisée.
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Message par djes »

Voilà un petit truc vite fait.

Code : Tout sélectionner

Enumeration
#Img1
#Img2
#Win
#Button
EndEnumeration

Procedure.l Ticks_HQ()
  Static maxfreq.q
  Protected t.q
  If maxfreq=0
    QueryPerformanceFrequency_(@maxfreq)
    maxfreq=maxfreq/1000
  EndIf
  QueryPerformanceCounter_(@t.q)
  ProcedureReturn t/maxfreq
EndProcedure


;Pour inverser les conventions RGB et BGR
Macro ReverseRGB(COLOR)
  (COLOR & $FF0000) >> 16 + (COLOR & $00FF00) + (COLOR & $0000FF) << 16
EndMacro

;Test si c'est un pixel de bordure
Macro BorderMap(BMP,X,Y)
  X=0 Or X=BMP\bmWidth-1 Or Y=0 Or Y=BMP\bmHeight-1
EndMacro

CreateImage(#Img1,360,240,32)
CreateImage(#Img2,360,240,32)

StartDrawing(ImageOutput(#Img1))
  Box(0,0,360,240,RGB(255,255,255))
  Circle(100,100,40,RGB(255,0,0))
  Circle(130,110,25,RGB(255,0,0))
  Circle(220,120,35,RGB(255,0,0))
  Box(140,100,60,30,RGB(255,0,0))
StopDrawing()

StartDrawing(ImageOutput(#Img2))
  Box(0,0,360,240,RGB(255,255,255))
StopDrawing()

*Address1=AllocateMemory(36)
*Address2=AllocateMemory(36)

Color=RGB(255,0,0)

GetObject_(ImageID(#Img1),SizeOf(BITMAP),@Img1.BITMAP)
GetObject_(ImageID(#Img2),SizeOf(BITMAP),@Img2.BITMAP)

For i=0 To 8 : PokeL(*Address2 + i*4, ReverseRGB(Color)) : Next i

;***************************************************************************************
;-Détection des contours

Time.l=Ticks_HQ()


n.l = ReverseRGB(Color)

*src.long = Img1\bmBits
*dst.long = Img2\bmBits

w_src.l = Img1\bmWidthBytes

For Y=0 To Img1\bmHeight-1

  For X=0 To Img1\bmWidth-1

    ;Si c'est un pixel de la bonne couleur
    If *src\l = n

      ;Si c'est un pixel de bordure
      ;Alors c'est un pixel de contour
      If BorderMap(Img1, X, Y)
        PokeL(*dst\l, 0)
      Else

        ;Si ce N'est PAS un pixel de bordure
        ;On teste les 9 pixels aux alentours


	!MOV   eax,dword [v_n]
	!MOV	 ebp,dword [p_src]
	!MOV	 edi,dword [p_dst]
	!SUB	 ebp,dword [v_w_src]

	!ADD	 ebp,-4
	!MOV	 ebx,dword [ebp]
	!CMP	 eax,ebx
	!JE    ENDIF1
	!MOV	 dword [edi],0
	!JMP	 l_cont
  !ENDIF1:

	!ADD	 ebp,4
	!MOV	 ebx,dword [ebp]
	!CMP	 eax,ebx
	!JE    ENDIF2
	!MOV	 dword [edi],0
	!JMP	 l_cont
  !ENDIF2:

	!ADD	 ebp,4
	!MOV	 ebx,dword [ebp]
	!CMP	 eax,ebx
	!JE    ENDIF3
	!MOV	 dword [edi],0
	!JMP	 l_cont
  !ENDIF3:

	!ADD	 ebp,dword [v_w_src]

	!MOV	 ebx,dword [ebp]
	!CMP	 eax,ebx
	!JE    ENDIF4
	!MOV	 dword [edi],0
	!JMP	 l_cont
  !ENDIF4:

	!ADD	 ebp,-4
	!MOV	 ebx,dword [ebp]
	!CMP	 eax,ebx
	!JE    ENDIF5
	!MOV	 dword [edi],0
	!JMP	 l_cont
  !ENDIF5:

	!ADD	 ebp,-4
	!MOV	 ebx,dword [ebp]
	!CMP	 eax,ebx
	!JE    ENDIF6
	!MOV	 dword [edi],0
	!JMP	 l_cont
  !ENDIF6:

	!ADD	 ebp,dword [v_w_src]

	!MOV	 ebx,dword [ebp]
	!CMP	 eax,ebx
	!JE    ENDIF7
	!MOV	 dword [edi],0
	!JMP	 l_cont
  !ENDIF7:

	!ADD	 ebp,4
	!MOV	 ebx,dword [ebp]
	!CMP	 eax,ebx
	!JE    ENDIF8
	!MOV	 dword [edi],0
	!JMP	 l_cont
  !ENDIF8:

	!ADD	 ebp,4
	!MOV	 ebx,dword [ebp]
	!CMP	 eax,ebx
	!JE    ENDIF9
	!MOV	 dword [edi],0
	!JMP	 l_cont
  !ENDIF9:


; ;----------------------

;         *src2.long=*src-w_src-4
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
;         *src2+4
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
;         *src2+4
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
; 
;         *src2+w_src
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
;         *src2-4
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
;         *src2-4
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
; 
;         *src2+w_src
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
;         *src2+4
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
;         *src2+4
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf

;-----------------------

;         *src-Img1\bmWidthBytes
;         tot = PeekL(*src-4)
;         tot = tot + PeekL(*src) + PeekL(*src+4)
;         *src+Img1\bmWidthBytes
;         tot = tot + PeekL(*src-4) + PeekL(*src) + PeekL(*src+4)
;         *src+Img1\bmWidthBytes
;         tot = tot + PeekL(*src-4) + PeekL(*src) + PeekL(*src+4)
;         *src-Img1\bmWidthBytes
;         If n<>(tot/9)
;           PokeL(*dst, 0)
;         EndIf
; 
;        CopyMemory(*src - 4 - Img1\bmWidthBytes, *Address1,      12)
;        CopyMemory(*src - 4                    , *Address1 + 12, 12)
;        CopyMemory(*src - 4 + Img1\bmWidthBytes, *Address1 + 24, 12)
; 
;         ;Si la couleur des 9 pixels enregistrés n'est pas identique
;         ;A la couleur de la région sélectionnée
;         ;Alors c'est un pixel de bordure
;         If Not CompareMemory(*Address1, *Address2, 36)
;          PokeL(*dst, 0)
;        EndIf

;------------------------

 CONT:

      EndIf
    EndIf

    *src + 4
    *dst + 4

  Next X

  *src + Img1\bmWidthBytes - (4 * Img1\bmWidth)
  *dst + Img2\bmWidthBytes - (4 * Img2\bmWidth)
  
Next Y

Time=Ticks_HQ()-Time

MessageRequester("Temps",Str(Time)+" ms")


;***************************************************************************************

OpenWindow(#Win,0,0,360,300,"Fenêtre",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
CreateGadgetList(WindowID(#Win))
ButtonGadget(#Button,150,250,60,40,"Changer")

Contour=0

;-Boucle principale

Repeat

Event=WaitWindowEvent()

Select Event
  Case #PB_Event_CloseWindow
    End
  Case #PB_Event_Gadget
    Event=EventGadget()
    Select Event
      Case #Button
        Contour=1-Contour
    EndSelect
EndSelect

StartDrawing(WindowOutput(#Win))
  If Not Contour
    DrawImage(ImageID(#Img1),0,0)
  Else
    DrawImage(ImageID(#Img2),0,0)
  EndIf
StopDrawing()

ForEver
Octavius
Messages : 312
Inscription : jeu. 26/juil./2007 12:10

Message par Octavius »

Bon ça vaut ce que ça vaut niveau précision, mais au lieu d'avoir 4 ms d'exécution avec ton code précédent, il n'y a maintenant plus qu' 1 ms ! :D :D :D (sans le débogueur évidemment)

Génial! 8O

Merci pour ton aide. Je vais essayer d'implémenter ça dans mon programme.
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Message par djes »

Juste une petite modif pour mieux voir le timing :

Code : Tout sélectionner

Enumeration
#Img1
#Img2
#Win
#Button
EndEnumeration

Procedure.l Ticks_HQ()
  Static maxfreq.q
  Protected t.q
  If maxfreq=0
    QueryPerformanceFrequency_(@maxfreq)
    maxfreq=maxfreq/1000
  EndIf
  QueryPerformanceCounter_(@t.q)
  ProcedureReturn t
EndProcedure


;Pour inverser les conventions RGB et BGR
Macro ReverseRGB(COLOR)
  (COLOR & $FF0000) >> 16 + (COLOR & $00FF00) + (COLOR & $0000FF) << 16
EndMacro

;Test si c'est un pixel de bordure
Macro BorderMap(BMP,X,Y)
  X=0 Or X=BMP\bmWidth-1 Or Y=0 Or Y=BMP\bmHeight-1
EndMacro

CreateImage(#Img1,360,240,32)
CreateImage(#Img2,360,240,32)

StartDrawing(ImageOutput(#Img1))
  Box(0,0,360,240,RGB(255,255,255))
  Circle(100,100,40,RGB(255,0,0))
  Circle(130,110,25,RGB(255,0,0))
  Circle(220,120,35,RGB(255,0,0))
  Box(140,100,60,30,RGB(255,0,0))
StopDrawing()

StartDrawing(ImageOutput(#Img2))
  Box(0,0,360,240,RGB(255,255,255))
StopDrawing()

*Address1=AllocateMemory(36)
*Address2=AllocateMemory(36)

Color=RGB(255,0,0)

GetObject_(ImageID(#Img1),SizeOf(BITMAP),@Img1.BITMAP)
GetObject_(ImageID(#Img2),SizeOf(BITMAP),@Img2.BITMAP)

For i=0 To 8 : PokeL(*Address2 + i*4, ReverseRGB(Color)) : Next i

;***************************************************************************************
;-Détection des contours

Time.l=Ticks_HQ()


n.l = ReverseRGB(Color)

*src.long = Img1\bmBits
*dst.long = Img2\bmBits

w_src.l = Img1\bmWidthBytes

For Y=0 To Img1\bmHeight-1

  For X=0 To Img1\bmWidth-1

    ;Si c'est un pixel de la bonne couleur
    If *src\l = n

      ;Si c'est un pixel de bordure
      ;Alors c'est un pixel de contour
      If BorderMap(Img1, X, Y)
        PokeL(*dst\l, 0)
      Else

        ;Si ce N'est PAS un pixel de bordure
        ;On teste les 9 pixels aux alentours


	!MOV   eax,dword [v_n]
	!MOV	 ebp,dword [p_src]
	!MOV	 edi,dword [p_dst]
	!SUB	 ebp,dword [v_w_src]

	!ADD	 ebp,-4
	!MOV	 ebx,dword [ebp]
	!CMP	 eax,ebx
	!JE    ENDIF1
	!MOV	 dword [edi],0
	!JMP	 l_cont
  !ENDIF1:

	!ADD	 ebp,4
	!MOV	 ebx,dword [ebp]
	!CMP	 eax,ebx
	!JE    ENDIF2
	!MOV	 dword [edi],0
	!JMP	 l_cont
  !ENDIF2:

	!ADD	 ebp,4
	!MOV	 ebx,dword [ebp]
	!CMP	 eax,ebx
	!JE    ENDIF3
	!MOV	 dword [edi],0
	!JMP	 l_cont
  !ENDIF3:

	!ADD	 ebp,dword [v_w_src]

	!MOV	 ebx,dword [ebp]
	!CMP	 eax,ebx
	!JE    ENDIF4
	!MOV	 dword [edi],0
	!JMP	 l_cont
  !ENDIF4:

	!ADD	 ebp,-4
	!MOV	 ebx,dword [ebp]
	!CMP	 eax,ebx
	!JE    ENDIF5
	!MOV	 dword [edi],0
	!JMP	 l_cont
  !ENDIF5:

	!ADD	 ebp,-4
	!MOV	 ebx,dword [ebp]
	!CMP	 eax,ebx
	!JE    ENDIF6
	!MOV	 dword [edi],0
	!JMP	 l_cont
  !ENDIF6:

	!ADD	 ebp,dword [v_w_src]

	!MOV	 ebx,dword [ebp]
	!CMP	 eax,ebx
	!JE    ENDIF7
	!MOV	 dword [edi],0
	!JMP	 l_cont
  !ENDIF7:

	!ADD	 ebp,4
	!MOV	 ebx,dword [ebp]
	!CMP	 eax,ebx
	!JE    ENDIF8
	!MOV	 dword [edi],0
	!JMP	 l_cont
  !ENDIF8:

	!ADD	 ebp,4
	!MOV	 ebx,dword [ebp]
	!CMP	 eax,ebx
	!JE    ENDIF9
	!MOV	 dword [edi],0
	!JMP	 l_cont
  !ENDIF9:


; ;----------------------

;         *src2.long=*src-w_src-4
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
;         *src2+4
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
;         *src2+4
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
; 
;         *src2+w_src
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
;         *src2-4
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
;         *src2-4
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
; 
;         *src2+w_src
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
;         *src2+4
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
;         *src2+4
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf

;-----------------------

;         *src-Img1\bmWidthBytes
;         tot = PeekL(*src-4)
;         tot = tot + PeekL(*src) + PeekL(*src+4)
;         *src+Img1\bmWidthBytes
;         tot = tot + PeekL(*src-4) + PeekL(*src) + PeekL(*src+4)
;         *src+Img1\bmWidthBytes
;         tot = tot + PeekL(*src-4) + PeekL(*src) + PeekL(*src+4)
;         *src-Img1\bmWidthBytes
;         If n<>(tot/9)
;           PokeL(*dst, 0)
;         EndIf
; 
;-----------------------
; 
;        CopyMemory(*src - 4 - Img1\bmWidthBytes, *Address1,      12)
;        CopyMemory(*src - 4                    , *Address1 + 12, 12)
;        CopyMemory(*src - 4 + Img1\bmWidthBytes, *Address1 + 24, 12)
; 
;         ;Si la couleur des 9 pixels enregistrés n'est pas identique
;         ;A la couleur de la région sélectionnée
;         ;Alors c'est un pixel de bordure
;         If Not CompareMemory(*Address1, *Address2, 36)
;          PokeL(*dst, 0)
;        EndIf

;------------------------

 CONT:

      EndIf
    EndIf

    *src + 4
    *dst + 4

  Next X

  *src + Img1\bmWidthBytes - (4 * Img1\bmWidth)
  *dst + Img2\bmWidthBytes - (4 * Img2\bmWidth)
  
Next Y

Time=Ticks_HQ()-Time

MessageRequester("Temps",Str(Time)+" ms")


;***************************************************************************************

OpenWindow(#Win,0,0,360,300,"Fenêtre",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
CreateGadgetList(WindowID(#Win))
ButtonGadget(#Button,150,250,60,40,"Changer")

Contour=0

;-Boucle principale

Repeat

Event=WaitWindowEvent()

Select Event
  Case #PB_Event_CloseWindow
    End
  Case #PB_Event_Gadget
    Event=EventGadget()
    Select Event
      Case #Button
        Contour=1-Contour
    EndSelect
EndSelect

StartDrawing(WindowOutput(#Win))
  If Not Contour
    DrawImage(ImageID(#Img1),0,0)
  Else
    DrawImage(ImageID(#Img2),0,0)
  EndIf
StopDrawing()

ForEver
Octavius
Messages : 312
Inscription : jeu. 26/juil./2007 12:10

Message par Octavius »

Si je mets le code dans une procédure ça ne marche plus... J'ai une erreur ASM "symbol undefined"... Pourquoi ? Comment faire ?

Code : Tout sélectionner

Enumeration
#Img1
#Img2
#Win
#Button
EndEnumeration

Procedure.f Ticks_HQ()
  Static maxfreq.q
  Protected t.q
  If maxfreq=0
    QueryPerformanceFrequency_(@maxfreq)
    maxfreq=maxfreq/1000
  EndIf
  QueryPerformanceCounter_(@t.q)
  ProcedureReturn t/maxfreq
EndProcedure

;Pour inverser les conventions RGB et BGR
Macro ReverseRGB(COLOR)
  (COLOR & $FF0000) >> 16 + (COLOR & $00FF00) + (COLOR & $0000FF) << 16
EndMacro

;Test si c'est un pixel de bordure
Macro BorderMap(BMP,X,Y)
  X=0 Or X=BMP\bmWidth-1 Or Y=0 Or Y=BMP\bmHeight-1
EndMacro

Procedure Proc()

*Address1=AllocateMemory(36)
*Address2=AllocateMemory(36)

Color=RGB(255,0,0)

GetObject_(ImageID(#Img1),SizeOf(BITMAP),@Img1.BITMAP)
GetObject_(ImageID(#Img2),SizeOf(BITMAP),@Img2.BITMAP)

For i=0 To 8 : PokeL(*Address2 + i*4, ReverseRGB(Color)) : Next i

n.l = ReverseRGB(Color)

*src.long = Img1\bmBits
*dst.long = Img2\bmBits

w_src.l = Img1\bmWidthBytes

For Y=0 To Img1\bmHeight-1

  For X=0 To Img1\bmWidth-1

    ;Si c'est un pixel de la bonne couleur
    If *src\l = n

      ;Si c'est un pixel de bordure
      ;Alors c'est un pixel de contour
      If BorderMap(Img1, X, Y)
        PokeL(*dst\l, 0)
      Else

        ;Si ce N'est PAS un pixel de bordure
        ;On teste les 9 pixels aux alentours


   !MOV   eax,dword [v_n]
   !MOV    ebp,dword [p_src]
   !MOV    edi,dword [p_dst]
   !SUB    ebp,dword [v_w_src]

   !ADD    ebp,-4
   !MOV    ebx,dword [ebp]
   !CMP    eax,ebx
   !JE    ENDIF1
   !MOV    dword [edi],0
   !JMP    l_cont
  !ENDIF1:

   !ADD    ebp,4
   !MOV    ebx,dword [ebp]
   !CMP    eax,ebx
   !JE    ENDIF2
   !MOV    dword [edi],0
   !JMP    l_cont
  !ENDIF2:

   !ADD    ebp,4
   !MOV    ebx,dword [ebp]
   !CMP    eax,ebx
   !JE    ENDIF3
   !MOV    dword [edi],0
   !JMP    l_cont
  !ENDIF3:

   !ADD    ebp,dword [v_w_src]

   !MOV    ebx,dword [ebp]
   !CMP    eax,ebx
   !JE    ENDIF4
   !MOV    dword [edi],0
   !JMP    l_cont
  !ENDIF4:

   !ADD    ebp,-4
   !MOV    ebx,dword [ebp]
   !CMP    eax,ebx
   !JE    ENDIF5
   !MOV    dword [edi],0
   !JMP    l_cont
  !ENDIF5:

   !ADD    ebp,-4
   !MOV    ebx,dword [ebp]
   !CMP    eax,ebx
   !JE    ENDIF6
   !MOV    dword [edi],0
   !JMP    l_cont
  !ENDIF6:

   !ADD    ebp,dword [v_w_src]

   !MOV    ebx,dword [ebp]
   !CMP    eax,ebx
   !JE    ENDIF7
   !MOV    dword [edi],0
   !JMP    l_cont
  !ENDIF7:

   !ADD    ebp,4
   !MOV    ebx,dword [ebp]
   !CMP    eax,ebx
   !JE    ENDIF8
   !MOV    dword [edi],0
   !JMP    l_cont
  !ENDIF8:

   !ADD    ebp,4
   !MOV    ebx,dword [ebp]
   !CMP    eax,ebx
   !JE    ENDIF9
   !MOV    dword [edi],0
   !JMP    l_cont
  !ENDIF9:


; ;----------------------

;         *src2.long=*src-w_src-4
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
;         *src2+4
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
;         *src2+4
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
;
;         *src2+w_src
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
;         *src2-4
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
;         *src2-4
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
;
;         *src2+w_src
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
;         *src2+4
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
;         *src2+4
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf

;-----------------------

;         *src-Img1\bmWidthBytes
;         tot = PeekL(*src-4)
;         tot = tot + PeekL(*src) + PeekL(*src+4)
;         *src+Img1\bmWidthBytes
;         tot = tot + PeekL(*src-4) + PeekL(*src) + PeekL(*src+4)
;         *src+Img1\bmWidthBytes
;         tot = tot + PeekL(*src-4) + PeekL(*src) + PeekL(*src+4)
;         *src-Img1\bmWidthBytes
;         If n<>(tot/9)
;           PokeL(*dst, 0)
;         EndIf
;
;-----------------------
;
;        CopyMemory(*src - 4 - Img1\bmWidthBytes, *Address1,      12)
;        CopyMemory(*src - 4                    , *Address1 + 12, 12)
;        CopyMemory(*src - 4 + Img1\bmWidthBytes, *Address1 + 24, 12)
;
;         ;Si la couleur des 9 pixels enregistrés n'est pas identique
;         ;A la couleur de la région sélectionnée
;         ;Alors c'est un pixel de bordure
;         If Not CompareMemory(*Address1, *Address2, 36)
;          PokeL(*dst, 0)
;        EndIf

;------------------------

 CONT:

      EndIf
    EndIf

    *src + 4
    *dst + 4

  Next X

  *src + Img1\bmWidthBytes - (4 * Img1\bmWidth)
  *dst + Img2\bmWidthBytes - (4 * Img2\bmWidth)
 
Next Y

EndProcedure

CreateImage(#Img1,360,240,32)
CreateImage(#Img2,360,240,32)

StartDrawing(ImageOutput(#Img1))
  Box(0,0,360,240,RGB(255,255,255))
  Circle(100,100,40,RGB(255,0,0))
  Circle(130,110,25,RGB(255,0,0))
  Circle(220,120,35,RGB(255,0,0))
  Box(140,100,60,30,RGB(255,0,0))
StopDrawing()

StartDrawing(ImageOutput(#Img2))
  Box(0,0,360,240,RGB(255,255,255))
StopDrawing()

;***************************************************************************************
;-Détection des contours

Time.f=Ticks_HQ()

Proc()

Time=Ticks_HQ()-Time

MessageRequester("Temps",StrF(Time)+" ms")


;***************************************************************************************

OpenWindow(#Win,0,0,360,300,"Fenêtre",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
CreateGadgetList(WindowID(#Win))
ButtonGadget(#Button,150,250,60,40,"Changer")

Contour=0

;-Boucle principale

Repeat

Event=WaitWindowEvent()

Select Event
  Case #PB_Event_CloseWindow
    End
  Case #PB_Event_Gadget
    Event=EventGadget()
    Select Event
      Case #Button
        Contour=1-Contour
    EndSelect
EndSelect

StartDrawing(WindowOutput(#Win))
  If Not Contour
    DrawImage(ImageID(#Img1),0,0)
  Else
    DrawImage(ImageID(#Img2),0,0)
  EndIf
StopDrawing()

ForEver
Octavius
Messages : 312
Inscription : jeu. 26/juil./2007 12:10

Message par Octavius »

C'est bon j'ai trouvé !!! Il faut rajouter "p." partout quand c'est une variable locale.

Code : Tout sélectionner

Enumeration
#Img1
#Img2
#Win
#Button
EndEnumeration

Procedure.f Ticks_HQ()
  Static maxfreq.q
  Protected t.q
  If maxfreq=0
    QueryPerformanceFrequency_(@maxfreq)
    maxfreq=maxfreq/1000
  EndIf
  QueryPerformanceCounter_(@t.q)
  ProcedureReturn t/maxfreq
EndProcedure

;Pour inverser les conventions RGB et BGR
Macro ReverseRGB(COLOR)
  (COLOR & $FF0000) >> 16 + (COLOR & $00FF00) + (COLOR & $0000FF) << 16
EndMacro

;Test si c'est un pixel de bordure
Macro BorderMap(BMP,X,Y)
  X=0 Or X=BMP\bmWidth-1 Or Y=0 Or Y=BMP\bmHeight-1
EndMacro

Procedure Proc()

*Address1=AllocateMemory(36)
*Address2=AllocateMemory(36)

Color=RGB(255,0,0)

GetObject_(ImageID(#Img1),SizeOf(BITMAP),@Img1.BITMAP)
GetObject_(ImageID(#Img2),SizeOf(BITMAP),@Img2.BITMAP)

For i=0 To 8 : PokeL(*Address2 + i*4, ReverseRGB(Color)) : Next i

n.l = ReverseRGB(Color)

*src.long = Img1\bmBits
*dst.long = Img2\bmBits

w_src.l = Img1\bmWidthBytes

For Y=0 To Img1\bmHeight-1

  For X=0 To Img1\bmWidth-1

    ;Si c'est un pixel de la bonne couleur
    If *src\l = n

      ;Si c'est un pixel de bordure
      ;Alors c'est un pixel de contour
      If BorderMap(Img1, X, Y)
        PokeL(*dst\l, 0)
      Else

        ;Si ce N'est PAS un pixel de bordure
        ;On teste les 9 pixels aux alentours


   !MOV   eax,dword [p.v_n]
   !MOV    ebp,dword [p.p_src]
   !MOV    edi,dword [p.p_dst]
   !SUB    ebp,dword [p.v_w_src]

   !ADD    ebp,-4
   !MOV    ebx,dword [ebp]
   !CMP    eax,ebx
   !JE    ENDIF1
   !MOV    dword [edi],0
   !JMP    l_cont
  !ENDIF1:

   !ADD    ebp,4
   !MOV    ebx,dword [ebp]
   !CMP    eax,ebx
   !JE    ENDIF2
   !MOV    dword [edi],0
   !JMP    l_cont
  !ENDIF2:

   !ADD    ebp,4
   !MOV    ebx,dword [ebp]
   !CMP    eax,ebx
   !JE    ENDIF3
   !MOV    dword [edi],0
   !JMP    l_cont
  !ENDIF3:

   !ADD    ebp,dword [p.v_w_src]

   !MOV    ebx,dword [ebp]
   !CMP    eax,ebx
   !JE    ENDIF4
   !MOV    dword [edi],0
   !JMP    l_cont
  !ENDIF4:

   !ADD    ebp,-4
   !MOV    ebx,dword [ebp]
   !CMP    eax,ebx
   !JE    ENDIF5
   !MOV    dword [edi],0
   !JMP    l_cont
  !ENDIF5:

   !ADD    ebp,-4
   !MOV    ebx,dword [ebp]
   !CMP    eax,ebx
   !JE    ENDIF6
   !MOV    dword [edi],0
   !JMP    l_cont
  !ENDIF6:

   !ADD    ebp,dword [p.v_w_src]

   !MOV    ebx,dword [ebp]
   !CMP    eax,ebx
   !JE    ENDIF7
   !MOV    dword [edi],0
   !JMP    l_cont
  !ENDIF7:

   !ADD    ebp,4
   !MOV    ebx,dword [ebp]
   !CMP    eax,ebx
   !JE    ENDIF8
   !MOV    dword [edi],0
   !JMP    l_cont
  !ENDIF8:

   !ADD    ebp,4
   !MOV    ebx,dword [ebp]
   !CMP    eax,ebx
   !JE    ENDIF9
   !MOV    dword [edi],0
   !JMP    l_cont
  !ENDIF9:


; ;----------------------

;         *src2.long=*src-w_src-4
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
;         *src2+4
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
;         *src2+4
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
;
;         *src2+w_src
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
;         *src2-4
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
;         *src2-4
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
;
;         *src2+w_src
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
;         *src2+4
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf
;         *src2+4
;         If *src2\l <> n
;           *dst\l = 0
;           Goto CONT
;         EndIf

;-----------------------

;         *src-Img1\bmWidthBytes
;         tot = PeekL(*src-4)
;         tot = tot + PeekL(*src) + PeekL(*src+4)
;         *src+Img1\bmWidthBytes
;         tot = tot + PeekL(*src-4) + PeekL(*src) + PeekL(*src+4)
;         *src+Img1\bmWidthBytes
;         tot = tot + PeekL(*src-4) + PeekL(*src) + PeekL(*src+4)
;         *src-Img1\bmWidthBytes
;         If n<>(tot/9)
;           PokeL(*dst, 0)
;         EndIf
;
;-----------------------
;
;        CopyMemory(*src - 4 - Img1\bmWidthBytes, *Address1,      12)
;        CopyMemory(*src - 4                    , *Address1 + 12, 12)
;        CopyMemory(*src - 4 + Img1\bmWidthBytes, *Address1 + 24, 12)
;
;         ;Si la couleur des 9 pixels enregistrés n'est pas identique
;         ;A la couleur de la région sélectionnée
;         ;Alors c'est un pixel de bordure
;         If Not CompareMemory(*Address1, *Address2, 36)
;          PokeL(*dst, 0)
;        EndIf

;------------------------

 CONT:

      EndIf
    EndIf

    *src + 4
    *dst + 4

  Next X

  *src + Img1\bmWidthBytes - (4 * Img1\bmWidth)
  *dst + Img2\bmWidthBytes - (4 * Img2\bmWidth)
 
Next Y

EndProcedure

CreateImage(#Img1,360,240,32)
CreateImage(#Img2,360,240,32)

StartDrawing(ImageOutput(#Img1))
  Box(0,0,360,240,RGB(255,255,255))
  Circle(100,100,40,RGB(255,0,0))
  Circle(130,110,25,RGB(255,0,0))
  Circle(220,120,35,RGB(255,0,0))
  Box(140,100,60,30,RGB(255,0,0))
StopDrawing()

StartDrawing(ImageOutput(#Img2))
  Box(0,0,360,240,RGB(255,255,255))
StopDrawing()

;***************************************************************************************
;-Détection des contours

Time.f=Ticks_HQ()

Proc()

Time=Ticks_HQ()-Time

MessageRequester("Temps",StrF(Time)+" ms")


;***************************************************************************************

OpenWindow(#Win,0,0,360,300,"Fenêtre",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
CreateGadgetList(WindowID(#Win))
ButtonGadget(#Button,150,250,60,40,"Changer")

Contour=0

;-Boucle principale

Repeat

Event=WaitWindowEvent()

Select Event
  Case #PB_Event_CloseWindow
    End
  Case #PB_Event_Gadget
    Event=EventGadget()
    Select Event
      Case #Button
        Contour=1-Contour
    EndSelect
EndSelect

StartDrawing(WindowOutput(#Win))
  If Not Contour
    DrawImage(ImageID(#Img1),0,0)
  Else
    DrawImage(ImageID(#Img2),0,0)
  EndIf
StopDrawing()

ForEver
Répondre