Filtre graphique

Pour discuter de l'assembleur
manababel
Messages : 105
Inscription : jeu. 14/mai/2020 7:40

Re: Filtre graphique

Message par manababel »

filtre roberts
c'est un filtre détection de contours,ce n'est pas le plus efficace,mais l'un des plus rapides
il est preferable d'utiliser un filtre de floutage avant (boxblur) puis le filtre threshodl après ( Black&white)

Code : Tout sélectionner

;*******************************************************************************
;Titre      : Filter_Roberts
;Date       : 27/04/2022
;Version PB : PureBasic 5.70 LTS
;             x64 seulement
;             Windows
;             linux - non testé
;             ios   - non testé
;
;Info       : ne fonctionne qu'avec des images 32bits ( source , cible et masque )
;             "la fonction "load_image" convertis les images 24bits en 32bits"    
;
;           : "Global Dim param(256)" est a declarer dans le programme principal
;*******************************************************************************

; valeur min = 0
; valeur 'mediane' = 128
; valeur max = 255
;Filter_Roberts( source , cible , option )
;Filter_Roberts( source , cible , option , mask )


Procedure Filter_Roberts_thread(i)

  Protected start,stop,p,s
  p = @param()

  start = ( param(4) / param(5) ) * i
  stop = ( param(4) / param(5) ) * (i + 1)
  If i = (param(5) - 1) ; ndt
    If stop < param(4) : stop = param(4) - 1 : EndIf
  EndIf 
  If stop > param(4)-1 : stop = param(4)-1 : EndIf
  
  Protected Dim Reg_memory.q(13*8+ 6*16 ) ; (6 registes 64bits) + (4 registes 128bits)
  s=@reg_memory() ; sauvegarde des registes
  !mov rax,[p.v_s]
  !mov [rax+000],rbx
  !mov [rax+008],rcx
  !mov [rax+016],rdx
  !mov [rax+024],rdi
  !mov [rax+032],rsi
  !mov [rax+040],r8
  !mov [rax+048],r9
  !mov [rax+054],r10
  !mov [rax+064],r11
  !mov [rax+072],r12
  !mov [rax+080],r13
  !mov [rax+088],r14
  !mov [rax+096],r15
  !movdqu [rax+104],xmm0
  !movdqu [rax+120],xmm1
  !movdqu [rax+136],xmm2
  !movdqu [rax+152],xmm3
  !movdqu [rax+168],xmm4
  !movdqu [rax+184],xmm5
  
  !mov rcx,[p.v_p]

  !pxor xmm0,xmm0
  !mov eax,[rcx+6*8] ; opt
  !imul eax,$10101
  !movd xmm5,eax
  !punpcklbw xmm5,xmm0
  
  !mov eax,[ecx+3*8] ; lg
  !mov r10,rax
  !dec r10 ; r10 = lg-1
  
  !mov eax,[p.v_stop];[ecx+4*8] ; ht
  !mov r11,rax
  
  !mov r9,[p.v_start] ; ht
  !mov eax,[ecx+3*8] ; lg
  !mul r9
  !shl rax,2
  !mov r9,rax
  
  !mov eax,[ecx+3*8] ; lg
  !shl eax,2
  !mov rsi,[rcx+00] ; source
  !add rsi,r9
  !mov rdi,rsi
  !add rdi,rax
  !mov rdx,[rcx+1*8] ; cible
  !add rdx,r9
  
  !mov r9,[p.v_start] ; ht
  !robert_boucle_y:
  
    !movd xmm1,[rsi]
    !movd xmm3,[rdi]
    !punpcklbw xmm1,xmm0
    !punpcklbw xmm3,xmm0
    
    !xor r8,r8
    !robert_boucle_x:
  
      !movd xmm2,[rsi+r8*4+4]
      !movd xmm4,[rdi+r8*4+4]
      !punpcklbw xmm2,xmm0
      !punpcklbw xmm4,xmm0

      !movq xmm10,xmm1 ; r=(Abs(Abs(rx)+Abs(ry))*Filter_Roberts_opt)
      !psubsw xmm10,xmm4
      !pabsw xmm10,xmm10 ; abs
   
      !movq xmm11,xmm2 ; 
      !psubsw xmm11,xmm3
      !pabsw xmm11,xmm11 ; abs
      
      !paddsw xmm10,xmm11 ; x=((rx+ry)*opt)/128
      !pmullw xmm10,xmm5
      !psrlw xmm10,7
      
      !packsswb xmm10,xmm0
      !movd [rdx+r8*4],xmm10
  
      !movq xmm1,xmm2 ;r1=r2
      !movq xmm3,xmm4

      !inc r8
      !cmp r8,r10 ; cmp (lg-1)
    !jb robert_boucle_x
    !mov eax,[ecx+3*8] ; lg
    !shl eax,2
    !add rdx,rax 
    !add rsi,rax
    !add rdi,rax
    !inc r9
    !cmp r9,r11 ; cmp (ht-1) 
  !jb robert_boucle_y    
 
  !mov rax,[p.v_s] ; restaurtion des registres
  !mov rbx,[rax+000]
  !mov rcx,[rax+008]
  !mov rdx,[rax+016]
  !mov rdi,[rax+024]
  !mov rsi,[rax+032]
  !mov r8,[rax+040]
  !mov r9,[rax+048]
  !mov r10,[rax+056]
  !mov r11,[rax+064]
  !mov r12,[rax+072]
  !mov r13,[rax+080]
  !mov r14,[rax+088]
  !mov r15,[rax+096]
  !movdqu xmm0,[rax+104]
  !movdqu xmm1,[rax+120]
  !movdqu xmm2,[rax+136]
  !movdqu xmm3,[rax+152]
  !movdqu xmm4,[rax+168]
  !movdqu xmm5,[rax+184]
  FreeArray(Reg_memory())
  
EndProcedure




Procedure Filter_Roberts_mask_thread(i)

  Protected start,stop,p,s
  p = @param()

  start = ( param(4) / param(5) ) * i
  stop = ( param(4) / param(5) ) * (i + 1)
  If i = (param(5) - 1) ; ndt
    If stop < param(4) : stop = param(4) - 1 : EndIf
  EndIf 
  If stop > param(4)-1 : stop = param(4)-1 : EndIf
  
  Protected Dim Reg_memory.q(13*8+ 6*16 ) ; (6 registes 64bits) + (4 registes 128bits)
  s=@reg_memory() ; sauvegarde des registes
  !mov rax,[p.v_s]
  !mov [rax+000],rbx
  !mov [rax+008],rcx
  !mov [rax+016],rdx
  !mov [rax+024],rdi
  !mov [rax+032],rsi
  !mov [rax+040],r8
  !mov [rax+048],r9
  !mov [rax+054],r10
  !mov [rax+064],r11
  !mov [rax+072],r12
  !mov [rax+080],r13
  !mov [rax+088],r14
  !mov [rax+096],r15
  !movdqu [rax+104],xmm0
  !movdqu [rax+120],xmm1
  !movdqu [rax+136],xmm2
  !movdqu [rax+152],xmm3
  !movdqu [rax+168],xmm4
  !movdqu [rax+184],xmm5
  
  !mov rcx,[p.v_p]

  !pxor xmm0,xmm0
  !mov eax,[rcx+6*8] ; opt
  !imul eax,$10101
  !movd xmm5,eax
  !punpcklbw xmm5,xmm0
  
  !mov eax,[ecx+3*8] ; lg
  !mov r10,rax
  !dec r10 ; r10 = lg-1
  
  !mov r9,[p.v_start] ; ht
  !mov eax,[ecx+3*8] ; lg
  !mul r9
  !shl rax,2
  !mov r9,rax
  
  !mov eax,[ecx+3*8] ; lg
  !shl eax,2
  !mov rsi,[rcx+00] ; source
  !add rsi,r9
  !mov rdi,rsi
  !add rdi,rax
  !mov rdx,[rcx+1*8] ; cible
  !add rdx,r9
  !mov r11,[rcx+2*8] ; mask
  !add r11,r9
  
  !mov r9,[p.v_start] ; ht
  !robert_boucle_y2:
  
    !movd xmm1,[rsi]
    !movd xmm3,[rdi]
    !punpcklbw xmm1,xmm0
    !punpcklbw xmm3,xmm0
    
    !xor r8,r8
    !robert_boucle_x2:
  
      !movd xmm2,[rsi+r8*4+4]
      !movd xmm4,[rdi+r8*4+4]
      !punpcklbw xmm2,xmm0
      !punpcklbw xmm4,xmm0

      !movq xmm10,xmm1 ; r=(Abs(Abs(rx)+Abs(ry))*Filter_Roberts_opt)
      !psubsw xmm10,xmm4
      !pabsw xmm10,xmm10 ; abs
   
      !movq xmm11,xmm2 ; 
      !psubsw xmm11,xmm3
      !pabsw xmm11,xmm11 ; abs
      
      !paddsw xmm10,xmm11 ; x=((rx+ry)*opt)/128
      !pmullw xmm10,xmm5
      !psrlw xmm10,7
      
      !packsswb xmm10,xmm0
      
        !movd r13d,xmm10 ; calcul du mask
        !mov r12d,[r11+r8*4] ; mask
        !and r13d,r12d ; modification dans le mask
        !xor r12d,$ffffffff
        !mov r14d,[rsi+r8*4] ; source
        !and r14d,r12d
        !or r14d,r13d ; ajout de la partie hors du mask
        !mov [rdx+r8*4],r14d
        
      !movq xmm1,xmm2 ;r1=r2
      !movq xmm3,xmm4

      !inc r8
      !cmp r8,r10 ; cmp (lg-1)
    !jb robert_boucle_x2
    !mov eax,[ecx+3*8] ; lg
    !shl eax,2
    !add rdx,rax 
    !add rsi,rax
    !add rdi,rax
    !add r11,rax
    
    !mov rax,[p.v_stop]
    ;!dec rax
    !inc r9
    !cmp r9,rax ; cmp (ht-1) 
  !jb robert_boucle_y2  
 
  !mov rax,[p.v_s] ; restaurtion des registres
  !mov rbx,[rax+000]
  !mov rcx,[rax+008]
  !mov rdx,[rax+016]
  !mov rdi,[rax+024]
  !mov rsi,[rax+032]
  !mov r8,[rax+040]
  !mov r9,[rax+048]
  !mov r10,[rax+056]
  !mov r11,[rax+064]
  !mov r12,[rax+072]
  !mov r13,[rax+080]
  !mov r14,[rax+088]
  !mov r15,[rax+096]
  !movdqu xmm0,[rax+104]
  !movdqu xmm1,[rax+120]
  !movdqu xmm2,[rax+136]
  !movdqu xmm3,[rax+152]
  !movdqu xmm4,[rax+168]
  !movdqu xmm5,[rax+184]
  FreeArray(Reg_memory())
  
EndProcedure



Procedure Filter_Roberts(Filter_Roberts_source,Filter_Roberts_cible,Filter_Roberts_opt=128,Filter_Roberts_mask=0)
 
  If Filter_Roberts_cible = 0 Or Filter_Roberts_source = 0 : ProcedureReturn : EndIf
  Protected thread , Psource , Pcible , Pmask , lg , ht , i
  
  thread=CountCPUs(#PB_System_CPUs)
  If thread<2:thread=1:EndIf

  Protected Dim tr.q(thread)
  
  StartDrawing(ImageOutput(Filter_Roberts_source))
  Psource = DrawingBuffer()
  lg = ImageWidth(Filter_Roberts_source)
  ht = ImageHeight(Filter_Roberts_source) 
  StopDrawing()
  
  StartDrawing(ImageOutput(Filter_Roberts_cible))
  Pcible = DrawingBuffer()
  StopDrawing()
  
  If Filter_Roberts_mask <> 0
    StartDrawing(ImageOutput(Filter_Roberts_mask))
    Pmask = DrawingBuffer()
    StopDrawing()
  EndIf
  
  param(0)=Psource
  param(1)=Pcible
  param(2)=Pmask
  param(3)=lg
  param(4)=ht
  param(5)=thread
  param(6)= Filter_Roberts_opt
  
  For i=0 To thread-1 : tr(i)=0 : Next
  For i=0 To thread-1
    While tr(i)=0   
      If Filter_Roberts_mask = 0
        tr(i)=CreateThread(@Filter_Roberts_thread(),i)
      Else
        tr(i)=CreateThread(@Filter_Roberts_mask_thread(),i)
      EndIf
    Wend
  Next
  For i=0 To thread-1
    If IsThread(tr(i))>0 : WaitThread(tr(i)) : EndIf 
  Next
  
  FreeArray(tr())
      
EndProcedure
Programme de test

Code : Tout sélectionner

;-- image plugins
UseGIFImageDecoder()
UseJPEG2000ImageDecoder()
UseJPEG2000ImageEncoder()
UseJPEGImageDecoder()
UseJPEGImageEncoder()
UsePNGImageDecoder()
UsePNGImageEncoder()
UseTGAImageDecoder()
UseTIFFImageDecoder()

Global Dim param(256)

;-- include files
IncludeFile "filtres\roberts.pbi"

; charge une image et la convertie en 32bit
;-------------------------------------------------------------------
Procedure load_image(nom,file$)
  Protected nom_p.i , temps_p.i , x.l , y.l , r.l,g.l,b.l , i.l
  Protected lg.l , ht.l , depth.l , temps.i  , dif.l , dif1.l

  LoadImage(nom,file$)
  If Not IsImage(nom) : ProcedureReturn 0 : EndIf
   
  StartDrawing(ImageOutput(nom))
  Depth=OutputDepth()
  StopDrawing()

  If Depth=24
    CopyImage(nom,temps)
    FreeImage(nom)
    StartDrawing(ImageOutput(temps))
    temps_p = DrawingBuffer()
    lg = ImageWidth(temps)
    ht = ImageHeight(temps)
    dif = DrawingBufferPitch() - (lg*3)
    StopDrawing()
    
  
    CreateImage(nom,lg,ht,32)
    StartDrawing(ImageOutput(nom))
    nom_p = DrawingBuffer()
    StopDrawing()
    
    For y=0 To ht-1
      For x=0 To lg-1
        i = ((y*lg)+x)*3
        r=PeekA(temps_p + i + 2 + dif1)
        g=PeekA(temps_p + i + 1 + dif1)
        b=PeekA(temps_p + i + 0 + dif1)
        PokeL(nom_p + ((y*lg)+x)*4 , r<<16 + g<<8 + b)
      Next
      dif1 = dif1 + dif
    Next
    
    FreeImage(temps) ; supprime l'image 24bits
    
  EndIf

  ProcedureReturn 1
EndProcedure
;------------------------------------------------------------------

;-- programme test
If OpenWindow(0, 0, 0, 800, 800, "roberts", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
  
  CreateMenu(0, WindowID(0))
    MenuTitle("Load")
    MenuItem( 1, "Load Image")
   MenuTitle("Save")   
    MenuItem( 2, "Save BMP")
    ;MenuItem( 3, "Save JPG")
    MenuItem( 4, "Save Clipboard")
  MenuTitle("Quit")
    MenuItem( 5, "Quit")
  MenuTitle("mask")
    MenuItem(6,"new mask")  
    
  TrackBarGadget(10, 10, 0, 512, 20, 0, 255 )
    SetGadgetState(10, 128)
    
  Repeat
    update = 0
    Event = WindowEvent()
    Select Event
      Case #PB_Event_Gadget
        Select EventGadget()
          Case 10
            r = GetGadgetState(10)
            update = 1
          Case 11
            g= GetGadgetState(11)
            update = 1
          Case 12
            b = GetGadgetState(12)
            update = 1
          Case 13
            r = GetGadgetState(13)
            g=r : b=r
            update = 1

        EndSelect
                
      Case #PB_Event_Menu
        Select EventMenu()
          Case 1
            source = 2
            If IsImage(source) : FreeImage(source) : EndIf
            If IsImage(cible) : FreeImage(cible) : cible = 0 : EndIf
            If IsImage(mask) : FreeImage(mask) : mask = 0 : EndIf
            file$ = OpenFileRequester("Image","","",0)
            If Not Load_Image(source,file$)
              source = 0
              MessageRequester("load_image","erreur de chargement",#PB_MessageRequester_Ok | #PB_MessageRequester_Error)
            Else
              cible = 3
              If IsImage(cible) : FreeImage(cible) : EndIf
              CopyImage(source,cible)
              StartDrawing(WindowOutput(0))
              If IsImage(cible) : DrawImage(ImageID(cible),0,30) : EndIf
              StopDrawing()
              r = GetGadgetState(10)
              update = 1
           EndIf
          
          Case 2
            nom$ = SaveFileRequester("Save BMP", "", "", 0)
            If nom$ <> "" : SaveImage(cible, nom$+".bmp" ,#PB_ImagePlugin_BMP ) : EndIf

          Case 4
            SetClipboardImage(cible)
            
          Case 5
            quit = 1
            
          Case 6
            If source <> 0
              StartDrawing(ImageOutput(source))
              Psource = DrawingBuffer()            
              lg = ImageWidth(source)            
              ht = ImageHeight(source) 
              StopDrawing()
              If IsImage(mask) : FreeImage(mask) : mask = 0 : EndIf
              mask = 4
              CreateImage(mask,lg,ht,32)
              StartDrawing(ImageOutput(mask))
              Circle(lg/2,ht/2,ht/4,$ffffff)
              Box(lg/8,ht/8,lg/6,ht/6,$ffffff)
              StopDrawing()
              r = GetGadgetState(10)
              update = 1
            EndIf
            
        EndSelect
      EndSelect
      
      If update = 1      
      t=ElapsedMilliseconds()
      Filter_Roberts(source,cible,r,mask)

        t=ElapsedMilliseconds() - t
        
        StartDrawing(WindowOutput(0))
        If IsImage(cible)
          DrawImage(ImageID(cible),0,30)
          DrawText(750,5,Str(t)+"     ")
        EndIf
        StopDrawing()
      EndIf
      
      
  Until Event = #PB_Event_CloseWindow Or quit=1

  CloseWindow(0)

EndIf
Shadow
Messages : 1304
Inscription : mer. 04/nov./2015 17:39

Re: Filtre graphique

Message par Shadow »

Tien j'avais pas vue ça, j'ai pas encore tester mais à mon avis ça dois décoiffé :D
Merci du partage.
Processeur: Intel Core I7-4790 - 4 Cœurs - 8 Thread: 3.60 Ghz.
Ram: 32 GB.
Disque: C: SDD 250 GB, D: 3 TB.
Vidéo: NVIDIA GeForce GTX 960: 2 GB DDR5.
Écran: Asus VX248 24 Pouces: 1920 x 1080.
Système: Windows 7 64 Bits.

PureBasic: 5.60 x64 Bits.
manababel
Messages : 105
Inscription : jeu. 14/mai/2020 7:40

Re: Filtre graphique

Message par manababel »

Filtre Prewitt
filtre de détection de contours

Code : Tout sélectionner

;*******************************************************************************
;Titre      : Filter_Prewitt
;Date       : 01/05/2022
;Version PB : PureBasic 5.70 LTS
;             x64 seulement
;             Windows
;             linux - non testé
;             ios   - non testé
;
;Info       : ne fonctionne qu'avec des images 32bits ( source , cible et masque )
;             "la fonction "load_image" convertis les images 24bits en 32bits"    
;
;           : "Global Dim param(256)" est a declarer dans le programme principal
;*******************************************************************************

; valeur min = 0
; valeur 'mediane' = 128
; valeur max = 255
;Filter_Prewitt( source , cible , option )
;Filter_Prewitt( source , cible , option , mask 


Procedure Filter_Prewitt_thread(i)

  Protected start,stop,p,s
  p = @param()

  start = ( param(4) / param(5) ) * i
  stop = ( param(4) / param(5) ) * (i + 1)
  If i = (param(5) - 1) ; ndt
    If stop <= param(4) : stop = param(4) - 2 : EndIf
  EndIf 
  If stop > param(4)-2 : stop = param(4)-2 : EndIf
  
  Protected Dim Reg_memory.q(13*8+ 16*16 ) ; (6 registes 64bits) + (4 registes 128bits)
  s=@reg_memory() ; sauvegarde des registes
  !mov rax,[p.v_s]
  !mov [rax+000],rbx
  !mov [rax+008],rcx
  !mov [rax+016],rdx
  !mov [rax+024],rdi
  !mov [rax+032],rsi
  !mov [rax+040],r8
  !mov [rax+048],r9
  !mov [rax+054],r10
  !mov [rax+064],r11
  !mov [rax+072],r12
  !mov [rax+080],r13
  !mov [rax+088],r14
  !mov [rax+096],r15
  !movdqu [rax+104],xmm0
  !movdqu [rax+120],xmm1
  !movdqu [rax+136],xmm2
  !movdqu [rax+152],xmm3
  !movdqu [rax+168],xmm4
  !movdqu [rax+184],xmm5
  !movdqu [rax+200],xmm6
  !movdqu [rax+216],xmm7
  !movdqu [rax+232],xmm8
  !movdqu [rax+248],xmm9
  !movdqu [rax+264],xmm10
  !movdqu [rax+280],xmm11
  !movdqu [rax+296],xmm12
  !movdqu [rax+312],xmm13
  !movdqu [rax+328],xmm14
  !movdqu [rax+344],xmm15
  
  !mov rcx,[p.v_p]
  
  !mov rax,[p.v_start]
  !imul rax,[rcx+3*8]
  !shl rax,2 
  !mov r12,[rcx+0] ; source
  !mov r11,[rcx+8] ; cible
  !add r12,rax ; source + start
  !add r11,rax ; cible + start 
  
  !add r11,4
  !mov r15,[rcx+3*8] ; lg
  !shl r15,2
  !pxor xmm0,xmm0
  !mov eax,[rcx+6*8] ; opt
  !imul eax,$10101
  !movd xmm15,eax
  !punpcklbw xmm15,xmm0
  
  !xor rax,rax
  !mov eax,[rcx+4*8] ; ht
  !mov r13,[p.v_start]
  !prewitt_boucle_y :
  
    !mov rsi,r12
    !mov rdi,r11
    !add r12,r15
    !add r11,r15
    
    !movd xmm1,[rsi]
    !movd xmm2,[rsi+4]
    !add rsi,r15
    !movd xmm4,[rsi]
    !movd xmm5,[rsi+4]
    !add rsi,r15
    !movd xmm7,[rsi]
    !movd xmm8,[rsi+4]
    !sub rsi,r15
    !sub rsi,r15
    
    !punpcklbw xmm1,xmm0
    !punpcklbw xmm2,xmm0
    !punpcklbw xmm4,xmm0
    !punpcklbw xmm5,xmm0
    !punpcklbw xmm7,xmm0
    !punpcklbw xmm8,xmm0
    
    !xor rax,rax
    !mov eax,[rcx+3*8] ; lg
    !mov r14,rax
    !sub r14,2

    !prewitt_boucle_x:
      !movd xmm3,[rsi+8]
      !add rsi,r15
      !movd xmm6,[rsi+8]
      !add rsi,r15
      !movd xmm9,[rsi+8]
      !sub rsi,r15
      !sub rsi,r15
      
      !punpcklbw xmm3,xmm0
      !punpcklbw xmm6,xmm0
      !punpcklbw xmm9,xmm0

      !movups xmm10,xmm1 ; ry=(x1 + x2 + x3) -( x7 + x8 + x9) x=rgb
      !paddusw xmm10,xmm2
      !paddusw xmm10,xmm3
      !movups xmm11,xmm7
      !paddusw xmm11,xmm8
      !paddusw xmm11,xmm9
      !psubsw xmm10,xmm11
      !pabsw xmm10,xmm10 ; abs
   
      !movups xmm12,xmm3 ; rx=(x3 + x6 + x9)-(x1 + x4 +x7)
      !paddusw xmm12,xmm6
      !paddusw xmm12,xmm9
      !movups xmm13,xmm1
      !paddusw xmm13,xmm4
      !paddusw xmm13,xmm7
      !psubsw xmm12,xmm13
      !pabsw xmm12,xmm12 ; abs
      
      !paddsw xmm10,xmm12 ; x=((rx+ry)*opt)/128
      !pmullw xmm10,xmm15
      !psrlw xmm10,7
      
      !packsswb xmm10,xmm0
      !movd [rdi],xmm10
      
      !add rdi,4
      !add rsi,4
  
      !movdqa xmm1,xmm2 ;r1=r2:r2=r3 : r4=r5:r5=r6 : r7=r8:r8=r9
      !movdqa xmm2,xmm3
      !movdqa xmm4,xmm5
      !movdqa xmm5,xmm6
      !movdqa xmm7,xmm8
      !movdqa xmm8,xmm9
      
      !sub r14,1
      !jnz prewitt_boucle_x
    !inc r13
    !cmp r13,[p.v_stop]  
    !jb prewitt_boucle_y  
 
  !mov rax,[p.v_s] ; restaurtion des registres
  !mov rbx,[rax+000]
  !mov rcx,[rax+008]
  !mov rdx,[rax+016]
  !mov rdi,[rax+024]
  !mov rsi,[rax+032]
  !mov r8,[rax+040]
  !mov r9,[rax+048]
  !mov r10,[rax+056]
  !mov r11,[rax+064]
  !mov r12,[rax+072]
  !mov r13,[rax+080]
  !mov r14,[rax+088]
  !mov r15,[rax+096]
  !movdqu xmm0,[rax+104]
  !movdqu xmm1,[rax+120]
  !movdqu xmm2,[rax+136]
  !movdqu xmm3,[rax+152]
  !movdqu xmm4,[rax+168]
  !movdqu xmm5,[rax+184]
  !movdqu xmm6,[rax+200]
  !movdqu xmm7,[rax+216]
  !movdqu xmm8,[rax+232]
  !movdqu xmm9,[rax+248]
  !movdqu xmm10,[rax+264]
  !movdqu xmm11,[rax+280]
  !movdqu xmm12,[rax+296]
  !movdqu xmm13,[rax+312]
  !movdqu xmm14,[rax+328]
  !movdqu xmm15,[rax+344]
  FreeArray(Reg_memory())
  
EndProcedure



Procedure Filter_Prewitt_mask_thread(i)

  Protected start,stop,p,s
  p = @param()

  start = ( param(4) / param(5) ) * i
  stop = ( param(4) / param(5) ) * (i + 1)
  If i = (param(5) - 1) ; ndt
    If stop <= param(4) : stop = param(4) - 2 : EndIf
  EndIf 
  If stop > param(4)-2 : stop = param(4)-2 : EndIf
  
  Protected Dim Reg_memory.q(13*8+ 16*16 ) ; (6 registes 64bits) + (4 registes 128bits)
  s=@reg_memory() ; sauvegarde des registes
  !mov rax,[p.v_s]
  !mov [rax+000],rbx
  !mov [rax+008],rcx
  !mov [rax+016],rdx
  !mov [rax+024],rdi
  !mov [rax+032],rsi
  !mov [rax+040],r8
  !mov [rax+048],r9
  !mov [rax+054],r10
  !mov [rax+064],r11
  !mov [rax+072],r12
  !mov [rax+080],r13
  !mov [rax+088],r14
  !mov [rax+096],r15
  !movdqu [rax+104],xmm0
  !movdqu [rax+120],xmm1
  !movdqu [rax+136],xmm2
  !movdqu [rax+152],xmm3
  !movdqu [rax+168],xmm4
  !movdqu [rax+184],xmm5
  !movdqu [rax+200],xmm6
  !movdqu [rax+216],xmm7
  !movdqu [rax+232],xmm8
  !movdqu [rax+248],xmm9
  !movdqu [rax+264],xmm10
  !movdqu [rax+280],xmm11
  !movdqu [rax+296],xmm12
  !movdqu [rax+312],xmm13
  !movdqu [rax+328],xmm14
  !movdqu [rax+344],xmm15
  
  !mov rcx,[p.v_p]
  
  !mov rax,[p.v_start]
  !imul rax,[rcx+3*8]
  !shl rax,2 
  !mov r12,[rcx+00] ; source
  !mov r11,[rcx+08] ; cible
  !mov rbx,[rcx+16] ; mask
  !add r12,rax ; source + start
  !add r11,rax ; cible + start 
  !add rbx,rax ; mask + start 
  
  !mov r15,[rcx+3*8] ; lg
  !shl r15,2
  !pxor xmm0,xmm0
  !mov eax,[rcx+6*8] ; opt
  !imul eax,$10101
  !movd xmm15,eax
  !punpcklbw xmm15,xmm0
  
  !xor rax,rax
  !mov eax,[rcx+4*8] ; ht
  !mov r13,[p.v_start]
  !prewitt_boucle_y2:
  
    !mov rsi,r12
    !mov rdi,r11
    !mov rdx,rbx
    !add r12,r15
    !add r11,r15
    !add rbx,r15
    
    !movd xmm1,[rsi]
    !movd xmm2,[rsi+4]
    !add rsi,r15
    !movd xmm4,[rsi]
    !movd xmm5,[rsi+4]
    !add rsi,r15
    !movd xmm7,[rsi]
    !movd xmm8,[rsi+4]
    !sub rsi,r15
    !sub rsi,r15
    
    !punpcklbw xmm1,xmm0
    !punpcklbw xmm2,xmm0
    !punpcklbw xmm4,xmm0
    !punpcklbw xmm5,xmm0
    !punpcklbw xmm7,xmm0
    !punpcklbw xmm8,xmm0
    
    !xor rax,rax
    !mov eax,[rcx+3*8] ; lg
    !mov r14,rax
    !sub r14,2

    !prewitt_boucle_x2:
      !movd xmm3,[rsi+8]
      !add rsi,r15
      !movd xmm6,[rsi+8]
      !add rsi,r15
      !movd xmm9,[rsi+8]
      !sub rsi,r15
      !sub rsi,r15
      
      !punpcklbw xmm3,xmm0
      !punpcklbw xmm6,xmm0
      !punpcklbw xmm9,xmm0

      !movups xmm10,xmm1 ; ry=(x1 + x2 + x3) -( x7 + x8 + x9) x=rgb
      !paddusw xmm10,xmm2
      !paddusw xmm10,xmm3
      !movups xmm11,xmm7
      !paddusw xmm11,xmm8
      !paddusw xmm11,xmm9
      !psubsw xmm10,xmm11
      !pabsw xmm10,xmm10 ; abs
   
      !movups xmm12,xmm3 ; rx=(x3 + x6 + x9)-(x1 + x4 +x7)
      !paddusw xmm12,xmm6
      !paddusw xmm12,xmm9
      !movups xmm13,xmm1
      !paddusw xmm13,xmm4
      !paddusw xmm13,xmm7
      !psubsw xmm12,xmm13
      !pabsw xmm12,xmm12 ; abs
      
      !paddsw xmm10,xmm12 ; x=((rx+ry)*opt)/128
      !pmullw xmm10,xmm15
      !psrlw xmm10,7
      !packsswb xmm10,xmm0
      ;!movd [rdi],xmm10
      
        !movd r8d,xmm10 ; calcul du mask
        !mov r9d,[rdx+4] ; mask
        !and r8d,r9d ; modification dans le mask
        !xor r9d,$ffffffff
        !mov r10d,[rsi+4] ; source
        !and r10d,r9d
        !or r10d,r8d ; ajout de la partie hors du mask
        !mov [rdi],r10d
        
      !add rdi,4
      !add rsi,4
      !add rdx,4
  
      !movdqa xmm1,xmm2 ;r1=r2:r2=r3 : r4=r5:r5=r6 : r7=r8:r8=r9
      !movdqa xmm2,xmm3
      !movdqa xmm4,xmm5
      !movdqa xmm5,xmm6
      !movdqa xmm7,xmm8
      !movdqa xmm8,xmm9
      
      !sub r14,1
      !jnz prewitt_boucle_x2
    !inc r13
    !cmp r13,[p.v_stop]  
    !jb prewitt_boucle_y2
 
  !mov rax,[p.v_s] ; restaurtion des registres
  !mov rbx,[rax+000]
  !mov rcx,[rax+008]
  !mov rdx,[rax+016]
  !mov rdi,[rax+024]
  !mov rsi,[rax+032]
  !mov r8,[rax+040]
  !mov r9,[rax+048]
  !mov r10,[rax+056]
  !mov r11,[rax+064]
  !mov r12,[rax+072]
  !mov r13,[rax+080]
  !mov r14,[rax+088]
  !mov r15,[rax+096]
  !movdqu xmm0,[rax+104]
  !movdqu xmm1,[rax+120]
  !movdqu xmm2,[rax+136]
  !movdqu xmm3,[rax+152]
  !movdqu xmm4,[rax+168]
  !movdqu xmm5,[rax+184]
  !movdqu xmm6,[rax+200]
  !movdqu xmm7,[rax+216]
  !movdqu xmm8,[rax+232]
  !movdqu xmm9,[rax+248]
  !movdqu xmm10,[rax+264]
  !movdqu xmm11,[rax+280]
  !movdqu xmm12,[rax+296]
  !movdqu xmm13,[rax+312]
  !movdqu xmm14,[rax+328]
  !movdqu xmm15,[rax+344]
  FreeArray(Reg_memory())
  
EndProcedure


Procedure Filter_Prewitt(Filter_Prewitt_source,Filter_Prewitt_cible,Filter_Prewitt_opt=128,Filter_Prewitt_mask=0)
 
  If Filter_Prewitt_cible = 0 Or Filter_Prewitt_source = 0 : ProcedureReturn : EndIf
  Protected thread , Psource , Pcible , Pmask , lg , ht , i
  
  thread=CountCPUs(#PB_System_CPUs)
  If thread<2:thread=1:EndIf

  Protected Dim tr.q(thread)
  
  StartDrawing(ImageOutput(Filter_Prewitt_source))
  Psource = DrawingBuffer()
  lg = ImageWidth(Filter_Prewitt_source)
  ht = ImageHeight(Filter_Prewitt_source) 
  StopDrawing()
  
  StartDrawing(ImageOutput(Filter_Prewitt_cible))
  Pcible = DrawingBuffer()
  StopDrawing()
  
  If Filter_Prewitt_mask <> 0
    StartDrawing(ImageOutput(Filter_Prewitt_mask))
    Pmask = DrawingBuffer()
    StopDrawing()
  EndIf
  
  param(0)=Psource
  param(1)=Pcible
  param(2)=Pmask
  param(3)=lg
  param(4)=ht
  param(5)=thread
  param(6)= Filter_Prewitt_opt
  
  For i=0 To thread-1 : tr(i)=0 : Next
  For i=0 To thread-1
    While tr(i)=0   
      If Filter_Prewitt_mask = 0
        tr(i)=CreateThread(@Filter_Prewitt_thread(),i)
      Else
        tr(i)=CreateThread(@Filter_Prewitt_mask_thread(),i)
      EndIf
    Wend
  Next
  For i=0 To thread-1
    If IsThread(tr(i))>0 : WaitThread(tr(i)) : EndIf 
  Next
  
  FreeArray(tr())
      
EndProcedure
Programme de test

Code : Tout sélectionner

;-- image plugins
UseGIFImageDecoder()
UseJPEG2000ImageDecoder()
UseJPEG2000ImageEncoder()
UseJPEGImageDecoder()
UseJPEGImageEncoder()
UsePNGImageDecoder()
UsePNGImageEncoder()
UseTGAImageDecoder()
UseTIFFImageDecoder()

Global Dim param(256)

;-- include files
IncludeFile "filtres\prewitt.pbi"

; charge une image et la convertie en 32bit
;-------------------------------------------------------------------
Procedure load_image(nom,file$)
  Protected nom_p.i , temps_p.i , x.l , y.l , r.l,g.l,b.l , i.l
  Protected lg.l , ht.l , depth.l , temps.i  , dif.l , dif1.l

  LoadImage(nom,file$)
  If Not IsImage(nom) : ProcedureReturn 0 : EndIf
   
  StartDrawing(ImageOutput(nom))
  Depth=OutputDepth()
  StopDrawing()

  If Depth=24
    CopyImage(nom,temps)
    FreeImage(nom)
    StartDrawing(ImageOutput(temps))
    temps_p = DrawingBuffer()
    lg = ImageWidth(temps)
    ht = ImageHeight(temps)
    dif = DrawingBufferPitch() - (lg*3)
    StopDrawing()
    
  
    CreateImage(nom,lg,ht,32)
    StartDrawing(ImageOutput(nom))
    nom_p = DrawingBuffer()
    StopDrawing()
    
    For y=0 To ht-1
      For x=0 To lg-1
        i = ((y*lg)+x)*3
        r=PeekA(temps_p + i + 2 + dif1)
        g=PeekA(temps_p + i + 1 + dif1)
        b=PeekA(temps_p + i + 0 + dif1)
        PokeL(nom_p + ((y*lg)+x)*4 , r<<16 + g<<8 + b)
      Next
      dif1 = dif1 + dif
    Next
    
    FreeImage(temps) ; supprime l'image 24bits
    
  EndIf

  ProcedureReturn 1
EndProcedure
;------------------------------------------------------------------

;-- programme test
If OpenWindow(0, 0, 0, 800, 800, "Prewitt", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
  
  CreateMenu(0, WindowID(0))
    MenuTitle("Load")
    MenuItem( 1, "Load Image")
   MenuTitle("Save")   
    MenuItem( 2, "Save BMP")
    ;MenuItem( 3, "Save JPG")
    MenuItem( 4, "Save Clipboard")
  MenuTitle("Quit")
    MenuItem( 5, "Quit")
  MenuTitle("mask")
    MenuItem(6,"new mask")  
    
  TrackBarGadget(10, 10, 0, 512, 20, 0, 255 )
    SetGadgetState(10, 128)
    
  Repeat
    update = 0
    Event = WindowEvent()
    Select Event
      Case #PB_Event_Gadget
        Select EventGadget()
          Case 10
            r = GetGadgetState(10)
            update = 1
          Case 11
            g= GetGadgetState(11)
            update = 1
          Case 12
            b = GetGadgetState(12)
            update = 1
          Case 13
            r = GetGadgetState(13)
            g=r : b=r
            update = 1

        EndSelect
                
      Case #PB_Event_Menu
        Select EventMenu()
          Case 1
            source = 2
            If IsImage(source) : FreeImage(source) : EndIf
            If IsImage(cible) : FreeImage(cible) : cible = 0 : EndIf
            If IsImage(mask) : FreeImage(mask) : mask = 0 : EndIf
            file$ = OpenFileRequester("Image","","",0)
            If Not Load_Image(source,file$)
              source = 0
              MessageRequester("load_image","erreur de chargement",#PB_MessageRequester_Ok | #PB_MessageRequester_Error)
            Else
              cible = 3
              If IsImage(cible) : FreeImage(cible) : EndIf
              CopyImage(source,cible)
              StartDrawing(WindowOutput(0))
              If IsImage(cible) : DrawImage(ImageID(cible),0,30) : EndIf
              StopDrawing()
              r = GetGadgetState(10)
              update = 1
           EndIf
          
          Case 2
            nom$ = SaveFileRequester("Save BMP", "", "", 0)
            If nom$ <> "" : SaveImage(cible, nom$+".bmp" ,#PB_ImagePlugin_BMP ) : EndIf

          Case 4
            SetClipboardImage(cible)
            
          Case 5
            quit = 1
            
          Case 6
            If source <> 0
              StartDrawing(ImageOutput(source))
              Psource = DrawingBuffer()            
              lg = ImageWidth(source)            
              ht = ImageHeight(source) 
              StopDrawing()
              If IsImage(mask) : FreeImage(mask) : mask = 0 : EndIf
              mask = 4
              CreateImage(mask,lg,ht,32)
              StartDrawing(ImageOutput(mask))
              Circle(lg/2,ht/2,ht/4,$ffffff)
              Box(lg/8,ht/8,lg/6,ht/6,$ffffff)
              StopDrawing()
              r = GetGadgetState(10)
              update = 1
            EndIf
            
        EndSelect
      EndSelect
      
      If update = 1      
      t=ElapsedMilliseconds()
      Filter_Prewitt(source,cible,r,mask)

        t=ElapsedMilliseconds() - t
        
        StartDrawing(WindowOutput(0))
        If IsImage(cible)
          DrawImage(ImageID(cible),0,30)
          DrawText(750,5,Str(t)+"     ")
        EndIf
        StopDrawing()
      EndIf
      
      
  Until Event = #PB_Event_CloseWindow Or quit=1

  CloseWindow(0)

EndIf
Shadow
Messages : 1304
Inscription : mer. 04/nov./2015 17:39

Re: Filtre graphique

Message par Shadow »

Ce serais bien de le mettre à jour pour la version 6.00 :)
Processeur: Intel Core I7-4790 - 4 Cœurs - 8 Thread: 3.60 Ghz.
Ram: 32 GB.
Disque: C: SDD 250 GB, D: 3 TB.
Vidéo: NVIDIA GeForce GTX 960: 2 GB DDR5.
Écran: Asus VX248 24 Pouces: 1920 x 1080.
Système: Windows 7 64 Bits.

PureBasic: 5.60 x64 Bits.
kwandjeen
Messages : 204
Inscription : dim. 16/juil./2006 21:44

Re: Filtre graphique

Message par kwandjeen »

Sympa tout ça. Bravo et merci pour le partage.
manababel
Messages : 105
Inscription : jeu. 14/mai/2020 7:40

Re: Filtre graphique

Message par manababel »

Filtre Sobel
filtre de détection de contours

Code : Tout sélectionner

;*******************************************************************************
;Titre      : Filter_Sobel
;Date       : 012/05/2022
;Version PB : PureBasic 5.70 LTS & 6.00 beta 7
;             x64 seulement
;             Windows
;             linux - non testé
;             ios   - non testé
;
;Info       : ne fonctionne qu'avec des images 32bits ( source , cible et masque )
;             "la fonction "load_image" convertis les images 24bits en 32bits"    
;
;           : "Global Dim param(256)" est a declarer dans le programme principal
;*******************************************************************************

; valeur min = 0
; valeur 'mediane' = 128
; valeur max = 255
;Filter_Sobel( source , cible , option )
;Filter_Sobel( source , cible , option , mask 


Procedure Filter_Sobel_thread(i)

  Protected start,stop,p,s
  p = @param()

  start = ( param(4) / param(5) ) * i
  stop = ( param(4) / param(5) ) * (i + 1)
  If i = (param(5) - 1) ; ndt
    If stop <= param(4) : stop = param(4) - 2 : EndIf
  EndIf 
  If stop > param(4)-2 : stop = param(4)-2 : EndIf
  
  Protected Dim Reg_memory.q(13*8+ 16*16 ) ; (6 registes 64bits) + (4 registes 128bits)
  s=@reg_memory() ; sauvegarde des registes
  !mov rax,[p.v_s]
  !mov [rax+000],rbx
  !mov [rax+008],rcx
  !mov [rax+016],rdx
  !mov [rax+024],rdi
  !mov [rax+032],rsi
  !mov [rax+040],r8
  !mov [rax+048],r9
  !mov [rax+054],r10
  !mov [rax+064],r11
  !mov [rax+072],r12
  !mov [rax+080],r13
  !mov [rax+088],r14
  !mov [rax+096],r15
  !movdqu [rax+104],xmm0
  !movdqu [rax+120],xmm1
  !movdqu [rax+136],xmm2
  !movdqu [rax+152],xmm3
  !movdqu [rax+168],xmm4
  !movdqu [rax+184],xmm5
  !movdqu [rax+200],xmm6
  !movdqu [rax+216],xmm7
  !movdqu [rax+232],xmm8
  !movdqu [rax+248],xmm9
  !movdqu [rax+264],xmm10
  !movdqu [rax+280],xmm11
  !movdqu [rax+296],xmm12
  !movdqu [rax+312],xmm13
  !movdqu [rax+328],xmm14
  !movdqu [rax+344],xmm15
  
  !mov rcx,[p.v_p]
  
  !mov rax,[p.v_start]
  !imul rax,[rcx+3*8]
  !shl rax,2 
  !mov r12,[rcx+0] ; source
  !mov r11,[rcx+8] ; cible
  !add r12,rax ; source + start
  !add r11,rax ; cible + start 
  
  !add r11,4
  !mov r15,[rcx+3*8] ; lg
  !shl r15,2
  !pxor xmm0,xmm0
  !mov eax,[rcx+6*8] ; opt
  !imul eax,$10101
  !movd xmm15,eax
  !punpcklbw xmm15,xmm0
  
  !xor rax,rax
  !mov eax,[rcx+4*8] ; ht
  !mov r13,[p.v_start]
  !Sobel_boucle_y :
  
    !mov rsi,r12
    !mov rdi,r11
    !add r12,r15
    !add r11,r15
    
    !movd xmm1,[rsi]
    !movd xmm2,[rsi+4]
    !add rsi,r15
    !movd xmm4,[rsi]
    !movd xmm5,[rsi+4]
    !add rsi,r15
    !movd xmm7,[rsi]
    !movd xmm8,[rsi+4]
    !sub rsi,r15
    !sub rsi,r15
    
    !punpcklbw xmm1,xmm0
    !punpcklbw xmm2,xmm0
    !punpcklbw xmm4,xmm0
    !punpcklbw xmm5,xmm0
    !punpcklbw xmm7,xmm0
    !punpcklbw xmm8,xmm0
    
    !xor rax,rax
    !mov eax,[rcx+3*8] ; lg
    !mov r14,rax
    !sub r14,2

    !Sobel_boucle_x:
      !movd xmm3,[rsi+8]
      !add rsi,r15
      !movd xmm6,[rsi+8]
      !add rsi,r15
      !movd xmm9,[rsi+8]
      !sub rsi,r15
      !sub rsi,r15
      
      !punpcklbw xmm3,xmm0
      !punpcklbw xmm6,xmm0
      !punpcklbw xmm9,xmm0

      !movups xmm10,xmm1 ; ry=(x1 + x2 + x3) -( x7 + x8 + x9) x=rgb
      !movups xmm14,xmm2
      !psllw xmm14,1
      !paddusw xmm10,xmm14
      !paddusw xmm10,xmm3
      !movups xmm11,xmm7
      !movups xmm14,xmm8
      !psllw xmm14,1
      !paddusw xmm11,xmm14
      !paddusw xmm11,xmm9
      !psubsw xmm10,xmm11
      !pabsw xmm10,xmm10 ; abs
   
      !movups xmm12,xmm3 ; rx=(x3 + x6 + x9)-(x1 + x4 +x7)
      !movups xmm14,xmm6
      !psllw xmm14,1
      !paddusw xmm12,xmm14
      !paddusw xmm12,xmm9
      !movups xmm13,xmm1
      !movups xmm14,xmm4
      !psllw xmm14,1
      !paddusw xmm13,xmm14
      !paddusw xmm13,xmm7
      !psubsw xmm12,xmm13
      !pabsw xmm12,xmm12 ; abs
      
      !paddsw xmm10,xmm12 ; x=((rx+ry)*opt)/128
      !pmullw xmm10,xmm15
      !psrlw xmm10,7
      
      !packsswb xmm10,xmm0
      !movd [rdi],xmm10
      
      !add rdi,4
      !add rsi,4
  
      !movdqa xmm1,xmm2 ;r1=r2:r2=r3 : r4=r5:r5=r6 : r7=r8:r8=r9
      !movdqa xmm2,xmm3
      !movdqa xmm4,xmm5
      !movdqa xmm5,xmm6
      !movdqa xmm7,xmm8
      !movdqa xmm8,xmm9
      
      !sub r14,1
      !jnz Sobel_boucle_x
    !inc r13
    !cmp r13,[p.v_stop]  
    !jb Sobel_boucle_y  
 
  !mov rax,[p.v_s] ; restaurtion des registres
  !mov rbx,[rax+000]
  !mov rcx,[rax+008]
  !mov rdx,[rax+016]
  !mov rdi,[rax+024]
  !mov rsi,[rax+032]
  !mov r8,[rax+040]
  !mov r9,[rax+048]
  !mov r10,[rax+056]
  !mov r11,[rax+064]
  !mov r12,[rax+072]
  !mov r13,[rax+080]
  !mov r14,[rax+088]
  !mov r15,[rax+096]
  !movdqu xmm0,[rax+104]
  !movdqu xmm1,[rax+120]
  !movdqu xmm2,[rax+136]
  !movdqu xmm3,[rax+152]
  !movdqu xmm4,[rax+168]
  !movdqu xmm5,[rax+184]
  !movdqu xmm6,[rax+200]
  !movdqu xmm7,[rax+216]
  !movdqu xmm8,[rax+232]
  !movdqu xmm9,[rax+248]
  !movdqu xmm10,[rax+264]
  !movdqu xmm11,[rax+280]
  !movdqu xmm12,[rax+296]
  !movdqu xmm13,[rax+312]
  !movdqu xmm14,[rax+328]
  !movdqu xmm15,[rax+344]
  FreeArray(Reg_memory())
  
EndProcedure



Procedure Filter_Sobel_mask_thread(i)

  Protected start,stop,p,s
  p = @param()

  start = ( param(4) / param(5) ) * i
  stop = ( param(4) / param(5) ) * (i + 1)
  If i = (param(5) - 1) ; ndt
    If stop <= param(4) : stop = param(4) - 2 : EndIf
  EndIf 
  If stop > param(4)-2 : stop = param(4)-2 : EndIf
  
  Protected Dim Reg_memory.q(13*8+ 16*16 ) ; (6 registes 64bits) + (4 registes 128bits)
  s=@reg_memory() ; sauvegarde des registes
  !mov rax,[p.v_s]
  !mov [rax+000],rbx
  !mov [rax+008],rcx
  !mov [rax+016],rdx
  !mov [rax+024],rdi
  !mov [rax+032],rsi
  !mov [rax+040],r8
  !mov [rax+048],r9
  !mov [rax+054],r10
  !mov [rax+064],r11
  !mov [rax+072],r12
  !mov [rax+080],r13
  !mov [rax+088],r14
  !mov [rax+096],r15
  !movdqu [rax+104],xmm0
  !movdqu [rax+120],xmm1
  !movdqu [rax+136],xmm2
  !movdqu [rax+152],xmm3
  !movdqu [rax+168],xmm4
  !movdqu [rax+184],xmm5
  !movdqu [rax+200],xmm6
  !movdqu [rax+216],xmm7
  !movdqu [rax+232],xmm8
  !movdqu [rax+248],xmm9
  !movdqu [rax+264],xmm10
  !movdqu [rax+280],xmm11
  !movdqu [rax+296],xmm12
  !movdqu [rax+312],xmm13
  !movdqu [rax+328],xmm14
  !movdqu [rax+344],xmm15
  
  !mov rcx,[p.v_p]
  
  !mov rax,[p.v_start]
  !imul rax,[rcx+3*8]
  !shl rax,2 
  !mov r12,[rcx+00] ; source
  !mov r11,[rcx+08] ; cible
  !mov rbx,[rcx+16] ; mask
  !add r12,rax ; source + start
  !add r11,rax ; cible + start 
  !add rbx,rax ; mask + start 
  
  !mov r15,[rcx+3*8] ; lg
  !shl r15,2
  !pxor xmm0,xmm0
  !mov eax,[rcx+6*8] ; opt
  !imul eax,$10101
  !movd xmm15,eax
  !punpcklbw xmm15,xmm0
  
  !xor rax,rax
  !mov eax,[rcx+4*8] ; ht
  !mov r13,[p.v_start]
  !Sobel_boucle_y2:
  
    !mov rsi,r12
    !mov rdi,r11
    !mov rdx,rbx
    !add r12,r15
    !add r11,r15
    !add rbx,r15
    
    !movd xmm1,[rsi]
    !movd xmm2,[rsi+4]
    !add rsi,r15
    !movd xmm4,[rsi]
    !movd xmm5,[rsi+4]
    !add rsi,r15
    !movd xmm7,[rsi]
    !movd xmm8,[rsi+4]
    !sub rsi,r15
    !sub rsi,r15
    
    !punpcklbw xmm1,xmm0
    !punpcklbw xmm2,xmm0
    !punpcklbw xmm4,xmm0
    !punpcklbw xmm5,xmm0
    !punpcklbw xmm7,xmm0
    !punpcklbw xmm8,xmm0
    
    !xor rax,rax
    !mov eax,[rcx+3*8] ; lg
    !mov r14,rax
    !sub r14,2

    !Sobel_boucle_x2:
      !movd xmm3,[rsi+8]
      !add rsi,r15
      !movd xmm6,[rsi+8]
      !add rsi,r15
      !movd xmm9,[rsi+8]
      !sub rsi,r15
      !sub rsi,r15
      
      !punpcklbw xmm3,xmm0
      !punpcklbw xmm6,xmm0
      !punpcklbw xmm9,xmm0

      !movups xmm10,xmm1 ; ry=(x1 + x2 + x3) -( x7 + x8 + x9) x=rgb
      !movups xmm14,xmm2
      !psllw xmm14,1
      !paddusw xmm10,xmm14
      !paddusw xmm10,xmm3
      !movups xmm11,xmm7
      !movups xmm14,xmm8
      !psllw xmm14,1
      !paddusw xmm11,xmm14
      !paddusw xmm11,xmm9
      !psubsw xmm10,xmm11
      !pabsw xmm10,xmm10 ; abs
   
      !movups xmm12,xmm3 ; rx=(x3 + x6 + x9)-(x1 + x4 +x7)
      !movups xmm14,xmm6
      !psllw xmm14,1
      !paddusw xmm12,xmm14
      !paddusw xmm12,xmm9
      !movups xmm13,xmm1
      !movups xmm14,xmm4
      !psllw xmm14,1
      !paddusw xmm13,xmm14
      !paddusw xmm13,xmm7
      !psubsw xmm12,xmm13
      !pabsw xmm12,xmm12 ; abs
      
      !paddsw xmm10,xmm12 ; x=((rx+ry)*opt)/128
      !pmullw xmm10,xmm15
      !psrlw xmm10,7
      !packsswb xmm10,xmm0
      ;!movd [rdi],xmm10
      
        !movd r8d,xmm10 ; calcul du mask
        !mov r9d,[rdx+4] ; mask
        !and r8d,r9d ; modification dans le mask
        !xor r9d,$ffffffff
        !mov r10d,[rsi+4] ; source
        !and r10d,r9d
        !or r10d,r8d ; ajout de la partie hors du mask
        !mov [rdi],r10d
        
      !add rdi,4
      !add rsi,4
      !add rdx,4
  
      !movdqa xmm1,xmm2 ;r1=r2:r2=r3 : r4=r5:r5=r6 : r7=r8:r8=r9
      !movdqa xmm2,xmm3
      !movdqa xmm4,xmm5
      !movdqa xmm5,xmm6
      !movdqa xmm7,xmm8
      !movdqa xmm8,xmm9
      
      !sub r14,1
      !jnz Sobel_boucle_x2
    !inc r13
    !cmp r13,[p.v_stop]  
    !jb Sobel_boucle_y2
 
  !mov rax,[p.v_s] ; restaurtion des registres
  !mov rbx,[rax+000]
  !mov rcx,[rax+008]
  !mov rdx,[rax+016]
  !mov rdi,[rax+024]
  !mov rsi,[rax+032]
  !mov r8,[rax+040]
  !mov r9,[rax+048]
  !mov r10,[rax+056]
  !mov r11,[rax+064]
  !mov r12,[rax+072]
  !mov r13,[rax+080]
  !mov r14,[rax+088]
  !mov r15,[rax+096]
  !movdqu xmm0,[rax+104]
  !movdqu xmm1,[rax+120]
  !movdqu xmm2,[rax+136]
  !movdqu xmm3,[rax+152]
  !movdqu xmm4,[rax+168]
  !movdqu xmm5,[rax+184]
  !movdqu xmm6,[rax+200]
  !movdqu xmm7,[rax+216]
  !movdqu xmm8,[rax+232]
  !movdqu xmm9,[rax+248]
  !movdqu xmm10,[rax+264]
  !movdqu xmm11,[rax+280]
  !movdqu xmm12,[rax+296]
  !movdqu xmm13,[rax+312]
  !movdqu xmm14,[rax+328]
  !movdqu xmm15,[rax+344]
  FreeArray(Reg_memory())
  
EndProcedure


Procedure Filter_Sobel(Filter_Sobel_source,Filter_Sobel_cible,Filter_Sobel_opt=128,Filter_Sobel_mask=0)
 
  If Filter_Sobel_cible = 0 Or Filter_Sobel_source = 0 : ProcedureReturn : EndIf
  Protected thread , Psource , Pcible , Pmask , lg , ht , i
  
  thread=CountCPUs(#PB_System_CPUs)
  If thread<2:thread=1:EndIf

  Protected Dim tr.q(thread)
  
  StartDrawing(ImageOutput(Filter_Sobel_source))
  Psource = DrawingBuffer()
  lg = ImageWidth(Filter_Sobel_source)
  ht = ImageHeight(Filter_Sobel_source) 
  StopDrawing()
  
  StartDrawing(ImageOutput(Filter_Sobel_cible))
  Pcible = DrawingBuffer()
  StopDrawing()
  
  If Filter_Sobel_mask <> 0
    StartDrawing(ImageOutput(Filter_Sobel_mask))
    Pmask = DrawingBuffer()
    StopDrawing()
  EndIf
  
  param(0)=Psource
  param(1)=Pcible
  param(2)=Pmask
  param(3)=lg
  param(4)=ht
  param(5)=thread
  param(6)= Filter_Sobel_opt
  
  For i=0 To thread-1 : tr(i)=0 : Next
  For i=0 To thread-1
    While tr(i)=0   
      If Filter_Sobel_mask = 0
        tr(i)=CreateThread(@Filter_Sobel_thread(),i)
      Else
        tr(i)=CreateThread(@Filter_Sobel_mask_thread(),i)
      EndIf
    Wend
  Next
  For i=0 To thread-1
    If IsThread(tr(i))>0 : WaitThread(tr(i)) : EndIf 
  Next
  
  FreeArray(tr())
      
EndProcedure
Programme de test

Code : Tout sélectionner

;-- image plugins
UseGIFImageDecoder()
UseJPEG2000ImageDecoder()
UseJPEG2000ImageEncoder()
UseJPEGImageDecoder()
UseJPEGImageEncoder()
UsePNGImageDecoder()
UsePNGImageEncoder()
UseTGAImageDecoder()
UseTIFFImageDecoder()

Global Dim param(256)

;-- include files
IncludeFile "filtres\sobel.pbi"

; charge une image et la convertie en 32bit
;-------------------------------------------------------------------
Procedure load_image(nom,file$)
  Protected nom_p.i , temps_p.i , x.l , y.l , r.l,g.l,b.l , i.l
  Protected lg.l , ht.l , depth.l , temps.i  , dif.l , dif1.l

  LoadImage(nom,file$)
  If Not IsImage(nom) : ProcedureReturn 0 : EndIf
   
  StartDrawing(ImageOutput(nom))
  Depth=OutputDepth()
  StopDrawing()

  If Depth=24
    CopyImage(nom,temps)
    FreeImage(nom)
    StartDrawing(ImageOutput(temps))
    temps_p = DrawingBuffer()
    lg = ImageWidth(temps)
    ht = ImageHeight(temps)
    dif = DrawingBufferPitch() - (lg*3)
    StopDrawing()
    
  
    CreateImage(nom,lg,ht,32)
    StartDrawing(ImageOutput(nom))
    nom_p = DrawingBuffer()
    StopDrawing()
    
    For y=0 To ht-1
      For x=0 To lg-1
        i = ((y*lg)+x)*3
        r=PeekA(temps_p + i + 2 + dif1)
        g=PeekA(temps_p + i + 1 + dif1)
        b=PeekA(temps_p + i + 0 + dif1)
        PokeL(nom_p + ((y*lg)+x)*4 , r<<16 + g<<8 + b)
      Next
      dif1 = dif1 + dif
    Next
    
    FreeImage(temps) ; supprime l'image 24bits
    
  EndIf

  ProcedureReturn 1
EndProcedure
;------------------------------------------------------------------

;-- programme test
If OpenWindow(0, 0, 0, 800, 800, "Sobel", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
  
  CreateMenu(0, WindowID(0))
    MenuTitle("Load")
    MenuItem( 1, "Load Image")
   MenuTitle("Save")   
    MenuItem( 2, "Save BMP")
    ;MenuItem( 3, "Save JPG")
    MenuItem( 4, "Save Clipboard")
  MenuTitle("Quit")
    MenuItem( 5, "Quit")
  MenuTitle("mask")
    MenuItem(6,"new mask")  
    
  TrackBarGadget(10, 10, 0, 512, 20, 0, 255 )
    SetGadgetState(10, 128)
    
  Repeat
    update = 0
    Event = WindowEvent()
    Select Event
      Case #PB_Event_Gadget
        Select EventGadget()
          Case 10
            r = GetGadgetState(10)
            update = 1
          Case 11
            g= GetGadgetState(11)
            update = 1
          Case 12
            b = GetGadgetState(12)
            update = 1
          Case 13
            r = GetGadgetState(13)
            g=r : b=r
            update = 1

        EndSelect
                
      Case #PB_Event_Menu
        Select EventMenu()
          Case 1
            source = 2
            If IsImage(source) : FreeImage(source) : EndIf
            If IsImage(cible) : FreeImage(cible) : cible = 0 : EndIf
            If IsImage(mask) : FreeImage(mask) : mask = 0 : EndIf
            file$ = OpenFileRequester("Image","","",0)
            If Not Load_Image(source,file$)
              source = 0
              MessageRequester("load_image","erreur de chargement",#PB_MessageRequester_Ok | #PB_MessageRequester_Error)
            Else
              cible = 3
              If IsImage(cible) : FreeImage(cible) : EndIf
              CopyImage(source,cible)
              StartDrawing(WindowOutput(0))
              If IsImage(cible) : DrawImage(ImageID(cible),0,30) : EndIf
              StopDrawing()
              r = GetGadgetState(10)
              update = 1
           EndIf
          
          Case 2
            nom$ = SaveFileRequester("Save BMP", "", "", 0)
            If nom$ <> "" : SaveImage(cible, nom$+".bmp" ,#PB_ImagePlugin_BMP ) : EndIf

          Case 4
            SetClipboardImage(cible)
            
          Case 5
            quit = 1
            
          Case 6
            If source <> 0
              StartDrawing(ImageOutput(source))
              Psource = DrawingBuffer()            
              lg = ImageWidth(source)            
              ht = ImageHeight(source) 
              StopDrawing()
              If IsImage(mask) : FreeImage(mask) : mask = 0 : EndIf
              mask = 4
              CreateImage(mask,lg,ht,32)
              StartDrawing(ImageOutput(mask))
              Circle(lg/2,ht/2,ht/4,$ffffff)
              Box(lg/8,ht/8,lg/6,ht/6,$ffffff)
              StopDrawing()
              r = GetGadgetState(10)
              update = 1
            EndIf
            
        EndSelect
      EndSelect
      
      If update = 1      
      t=ElapsedMilliseconds()
      Filter_Sobel(source,cible,r,mask)

        t=ElapsedMilliseconds() - t
        
        StartDrawing(WindowOutput(0))
        If IsImage(cible)
          DrawImage(ImageID(cible),0,30)
          ;DrawText(750,5,Str(t)+"     ")
        EndIf
        StopDrawing()
      EndIf
      
      
  Until Event = #PB_Event_CloseWindow Or quit=1

  CloseWindow(0)

EndIf
manababel
Messages : 105
Inscription : jeu. 14/mai/2020 7:40

Re: Filtre graphique

Message par manababel »

filtre teinte
chnage la teinte de l'image
inclut une vesion en purebasic

Code : Tout sélectionner

;*******************************************************************************
;Titre      : Filter_Teinte
;Date       : 22/05/2022
;Version PB : PureBasic 5.70 LTS & 6.00 beta 7
;             x64 seulement
;             Windows
;             linux - non testé
;             ios   - non testé
;
;Info       : ne fonctionne qu'avec des images 32bits ( source , cible et masque )
;             "la fonction "load_image" convertis les images 24bits en 32bits"    
;
;           : "Global Dim param(256)" est a declarer dans le programme principal
;*******************************************************************************

; valeur min = 0
; valeur max = 360
;Filter_teinte( source , cible , option )
;Filter_teinte( source , cible , option , mask )

Procedure Filter_teinte_thread_pb(i) 
  
  Protected start,stop,p,c.l,s.l,d.f,angle.f
  Protected r,g,b,ry,by,y,ryy,byy,gy
  p = @param()

  start = (( param(3) * param(4) ) / param(5)) * i
  stop = (( param(3) * param(4) ) / param(5)) * ( i + 1 )
  If i = param(5) - 1
    If stop < (param(3) * param(4)) : stop = param(3) * param(4) : EndIf
  EndIf
  
  angle=(3.14*param(6))/180
  c=Cos(angle)*256
  s=Sin(angle)*256
  d=1/100
  For i=start*4 To (stop*4)-4 Step 4 
    var=PeekL(param(0)+i) 
    r = ( var >> 16) & 255
    g = ( var >> 8 ) & 255
    b = var & 255  
    
    RY = ( 70 * r - 59 * g - 11 * b ) *d
    BY = (-30 * r - 59 * g + 89 * b ) *d
    Y  = ( 30 * r + 59 * g + 11 * b ) *d
    
    RYY = ( S * BY + C * RY ) >>8;
    BYY = ( C * BY - S * RY ) >>8;
    
    GYY = (-51 * RYY - 19 * BYY ) *d
    
    r = Y + RYY                        
    g = Y + GYY; 
    b = Y + BYY;  
    If r < 0 : r = 0 : EndIf
    If g < 0 : g = 0 : EndIf
    If b < 0 : b = 0 : EndIf
    If r >255 : r = 255 : EndIf
    If g >255 : g = 255 : EndIf
    If b >255 : b = 255 : EndIf
    PokeL(param(1)+i,r<<16+g<<8+b)           
  Next

EndProcedure


Procedure Filter_teinte_thread(i) 
  
  Protected start,stop,p,c.l,s.l,d.f,angle.f,s2.l,m.q
  p = @param()

  start = (( param(3) * param(4) ) / param(5)) * i
  stop = (( param(3) * param(4) ) / param(5)) * ( i + 1 )
  If i = param(5) - 1
    If stop < (param(3) * param(4)) : stop = param(3) * param(4) : EndIf
  EndIf
  
  angle=(3.14*param(6))/180
  c=Cos(angle)*256
  s=Sin(angle)*256
  s2=-s
  d=1/100
  
  Protected Dim Reg_memory.q(13*8+ 16*16 ) ; (6 registes 64bits) + (4 registes 128bits)
  m=@reg_memory() ; sauvegarde des registes
  !mov rax,[p.v_m]
  !mov [rax+000],rbx
  !mov [rax+008],rcx
  !mov [rax+016],rdx
  !mov [rax+024],rdi
  !mov [rax+032],rsi
  !mov [rax+040],r8
  !mov [rax+048],r9
  !mov [rax+054],r10
  !mov [rax+064],r11
  !mov [rax+072],r12
  !mov [rax+080],r13
  !mov [rax+088],r14
  !mov [rax+096],r15
  !movdqu [rax+104],xmm0
  !movdqu [rax+120],xmm1
  !movdqu [rax+136],xmm2
  !movdqu [rax+152],xmm3
  !movdqu [rax+168],xmm4
  !movdqu [rax+184],xmm5
  !movdqu [rax+200],xmm6
  !movdqu [rax+216],xmm7
  !movdqu [rax+232],xmm8
  !movdqu [rax+248],xmm9
  !movdqu [rax+264],xmm10
  !movdqu [rax+280],xmm11
  !movdqu [rax+296],xmm12
  !movdqu [rax+312],xmm13
  !movdqu [rax+328],xmm14
  !movdqu [rax+344],xmm15
  
  !xor rax,rax
  
  !movd xmm4,[p.v_d]
  !pshufd xmm4,xmm4,0  ; d | d | d | d
  
  !mov rax,$0046ffc5fff5 ; 0 | 70 | -59 | -11
  !mov rbx,$0000ffffffff
  !movq xmm5,rax
  !movq xmm0,rbx
  !punpcklwd xmm5,xmm0 ; 16 -> 32 bits
  
  !mov rax,$ffe2ffc50059 ; 0 | -30 | -59 | 89
  !mov rbx,$ffffffff0000
  !movq xmm6,rax
  !movq xmm0,rbx
  !punpcklwd xmm6,xmm0 ; 16 -> 32
  
  !mov rax,$001e003b000b ; 0 |  30 |  59 | 11
  !movq xmm7,rax
  !pxor xmm0,xmm0
  !punpcklwd xmm7,xmm0 ; 16 -> 32 
  
  !mov eax,[p.v_c]
  !mov ebx,[p.v_s]
  !shl rbx,32
  !or rax,rbx
  !movq xmm8,rax ; 0 | 0 | sin | cos
  !pslldq xmm8,8
  
  !mov eax,[p.v_s2]
  !mov ebx,[p.v_c]
  !shl rbx,32
  !or rax,rbx
  !movq xmm9,rax ; 0 | 0 | cos | -sin
  !por xmm8,xmm9
  
  !mov eax,$ffffffcd ; -51
  !movd xmm9,eax
  !mov eax,$ffffffed ; -19
  !movd xmm10,eax
  !pslldq xmm10,8
  !por xmm9,xmm10
  
  !mov rcx,[p.v_p]
  !mov rdx,[rcx+00] ; source
  !mov rcx,[rcx+08] ; cible
 
  
  !mov r8,[p.v_start]
  !Filter_teinte_saut_01:

    !movd xmm1,[rdx+r8*4] ; peekl
    !punpcklbw xmm1,xmm0 ; 08 > 16 
    !punpcklwd xmm1,xmm0 ; 16 > 32
    !movdqu xmm2,xmm1
    !movdqu xmm3,xmm1
    
    !pmulld xmm1,xmm5 ;  70 * r | -59 * g | -11 * b
    !pmulld xmm2,xmm6 ; -30 * r | -59 * g |  89 * b
    !pmulld xmm3,xmm7 ;  30 * r |  59 * g |  11 * b
    !phaddd xmm1,xmm1 ;  0 + (70*r) | (-59*g) + (-11*b)
    !phaddd xmm2,xmm2
    !phaddd xmm3,xmm3
    !phaddd xmm1,xmm1 ; 0 + (70*r) + (-59*g) + (-11*b)
    !phaddd xmm2,xmm2
    !phaddd xmm3,xmm3
    
    !punpckldq xmm1,xmm2 ; by | ry | by | ry
    !pslldq xmm1,4 ; ry | by | ry | 0
    !mov eax,$ffff
    !movd xmm2,eax
    !pand xmm3,xmm2
    !por xmm1,xmm3 ; ; ry | by | ry | y
    
    !cvtdq2ps xmm1,xmm1
    !mulps xmm1,xmm4
    !cvtps2dq xmm1,xmm1 ; ry*d | by*d | ry*d | y*d
    ;RY = ( 70 * r - 59 * g - 11 * b ) *d
    ;BY = (-30 * r - 59 * g + 89 * b ) *d
    ;Y  = ( 30 * r + 59 * g + 11 * b ) *d
    
    !movdqu xmm10,xmm1
    !pshufd xmm10,xmm10,0 ; y | y | y | y
    !psrldq xmm1,4 ; 0 | ry*d | by*d | ry*d
    !movdqu xmm2,xmm1
    
    !punpckldq xmm1,xmm1 ; by | ry | by | ry
    
    !pmulld xmm1,xmm8 ; ( S * BY + C * RY ) | ( C * BY - S * RY )
    !phaddd xmm1,xmm1
    !psrad xmm1,8 ; ? | ? | byy | ryy
    !movq xmm2,xmm1
    ;RYY = ( S * BY + C * RY ) >>8;
    ;BYY = ( C * BY - S * RY ) >>8;
    
    !pmulld xmm1,xmm9
    !phaddd xmm1,xmm1
    !cvtdq2ps xmm1,xmm1
    !mulps xmm1,xmm4
    !cvtps2dq xmm1,xmm1 ; xmm1 = GYY = (-51 * RYY - 19 * BYY ) *d
    
    !mov rax,$ffffffff
    !movq xmm3,rax
    !pshufd xmm3,xmm3,$44 ; $00000000 | $ffffffff | $00000000 | $ffffffff
    !pshufd xmm2,xmm2,1 ; ryy | ryy | ryy | byy
    !pand xmm2,xmm3 ;       0 | ryy | 0   | byy
    
    !mov eax,$ffffffff
    !movd xmm3,eax
    !pand xmm1,xmm3 ; 0 | 0 | 0 | gyy
    !pslldq xmm1,4 ; 0 | 0 | gyy | 00
    
    !por xmm1,xmm2 ; 0 | ryy | gyy | byy
    
    !paddd xmm1,xmm10 ; y | ryy+y | gyy+y | byy+y
    
    !packusdw xmm1,xmm1 ; 32 -> 16
    !packuswb xmm1,xmm1 ; 16 -> 8
    !movd [rcx+r8*4],xmm1 ; pokel
    !inc r8
    !cmp r8,[p.v_stop]
  !jb Filter_teinte_saut_01

  !mov rax,[p.v_m] ; restaurtion des registres
  !mov rbx,[rax+000]
  !mov rcx,[rax+008]
  !mov rdx,[rax+016]
  !mov rdi,[rax+024]
  !mov rsi,[rax+032]
  !mov r8,[rax+040]
  !mov r9,[rax+048]
  !mov r10,[rax+056]
  !mov r11,[rax+064]
  !mov r12,[rax+072]
  !mov r13,[rax+080]
  !mov r14,[rax+088]
  !mov r15,[rax+096]
  !movdqu xmm0,[rax+104]
  !movdqu xmm1,[rax+120]
  !movdqu xmm2,[rax+136]
  !movdqu xmm3,[rax+152]
  !movdqu xmm4,[rax+168]
  !movdqu xmm5,[rax+184]
  !movdqu xmm6,[rax+200]
  !movdqu xmm7,[rax+216]
  !movdqu xmm8,[rax+232]
  !movdqu xmm9,[rax+248]
  !movdqu xmm10,[rax+264]
  !movdqu xmm11,[rax+280]
  !movdqu xmm12,[rax+296]
  !movdqu xmm13,[rax+312]
  !movdqu xmm14,[rax+328]
  !movdqu xmm15,[rax+344]
  FreeArray(Reg_memory())
  
EndProcedure


Procedure Filter_teinte_mask_thread(i) 
  
  Protected start,stop,p,c.l,s.l,d.f,angle.f,s2.l,m.q
  p = @param()

  start = (( param(3) * param(4) ) / param(5)) * i
  stop = (( param(3) * param(4) ) / param(5)) * ( i + 1 )
  If i = param(5) - 1
    If stop < (param(3) * param(4)) : stop = param(3) * param(4) : EndIf
  EndIf
  
  angle=(3.14*param(6))/180
  c=Cos(angle)*256
  s=Sin(angle)*256
  s2=-s
  d=1/100
  
  Protected Dim Reg_memory.q(13*8+ 16*16 ) ; (6 registes 64bits) + (4 registes 128bits)
  m=@reg_memory() ; sauvegarde des registes
  !mov rax,[p.v_m]
  !mov [rax+000],rbx
  !mov [rax+008],rcx
  !mov [rax+016],rdx
  !mov [rax+024],rdi
  !mov [rax+032],rsi
  !mov [rax+040],r8
  !mov [rax+048],r9
  !mov [rax+054],r10
  !mov [rax+064],r11
  !mov [rax+072],r12
  !mov [rax+080],r13
  !mov [rax+088],r14
  !mov [rax+096],r15
  !movdqu [rax+104],xmm0
  !movdqu [rax+120],xmm1
  !movdqu [rax+136],xmm2
  !movdqu [rax+152],xmm3
  !movdqu [rax+168],xmm4
  !movdqu [rax+184],xmm5
  !movdqu [rax+200],xmm6
  !movdqu [rax+216],xmm7
  !movdqu [rax+232],xmm8
  !movdqu [rax+248],xmm9
  !movdqu [rax+264],xmm10
  !movdqu [rax+280],xmm11
  !movdqu [rax+296],xmm12
  !movdqu [rax+312],xmm13
  !movdqu [rax+328],xmm14
  !movdqu [rax+344],xmm15
  
  !movd xmm4,[p.v_d]
  !pshufd xmm4,xmm4,0  ; d | d | d | d
  
  !mov rax,$0046ffc5fff5 ; 0 | 70 | -59 | -11
  !mov rbx,$0000ffffffff
  !movq xmm5,rax
  !movq xmm0,rbx
  !punpcklwd xmm5,xmm0 ; 16 -> 32 bits
  
  !mov rax,$ffe2ffc50059 ; 0 | -30 | -59 | 89
  !mov rbx,$ffffffff0000
  !movq xmm6,rax
  !movq xmm0,rbx
  !punpcklwd xmm6,xmm0 ; 16 -> 32
  
  !mov rax,$001e003b000b ; 0 |  30 |  59 | 11
  !movq xmm7,rax
  !pxor xmm0,xmm0
  !punpcklwd xmm7,xmm0 ; 16 -> 32 
  
  !mov eax,[p.v_c]
  !mov ebx,[p.v_s]
  !shl rbx,32
  !or rax,rbx
  !movq xmm8,rax ; 0 | 0 | sin | cos
  !pslldq xmm8,8
  
  !mov eax,[p.v_s2]
  !mov ebx,[p.v_c]
  !shl rbx,32
  !or rax,rbx
  !movq xmm9,rax ; 0 | 0 | cos | -sin
  !por xmm8,xmm9
  
  !mov eax,$ffffffcd ; -51
  !movd xmm9,eax
  !mov eax,$ffffffed ; -19
  !movd xmm10,eax
  !pslldq xmm10,8
  !por xmm9,xmm10
  
  !mov rcx,[p.v_p]
  !mov rdx,[rcx+00] ; source
  !mov rbx,[rcx+08] ; cible
  !mov rcx,[rcx+16] ; mask

  !mov r8,[p.v_start]
  !Filter_teinte_mask_saut_01:

    !movd xmm1,[rdx+r8*4] ; peekl
    !punpcklbw xmm1,xmm0 ; 08 > 16 
    !punpcklwd xmm1,xmm0 ; 16 > 32
    !movdqu xmm2,xmm1
    !movdqu xmm3,xmm1
    
    !pmulld xmm1,xmm5 ;  70 * r | -59 * g | -11 * b
    !pmulld xmm2,xmm6 ; -30 * r | -59 * g |  89 * b
    !pmulld xmm3,xmm7 ;  30 * r |  59 * g |  11 * b
    !phaddd xmm1,xmm1 ;  0 + (70*r) | (-59*g) + (-11*b)
    !phaddd xmm2,xmm2
    !phaddd xmm3,xmm3
    !phaddd xmm1,xmm1 ; 0 + (70*r) + (-59*g) + (-11*b)
    !phaddd xmm2,xmm2
    !phaddd xmm3,xmm3
    
    !punpckldq xmm1,xmm2 ; by | ry | by | ry
    !pslldq xmm1,4 ; ry | by | ry | 0
    !mov eax,$ffff
    !movd xmm2,eax
    !pand xmm3,xmm2
    !por xmm1,xmm3 ; ; ry | by | ry | y
    
    !cvtdq2ps xmm1,xmm1
    !mulps xmm1,xmm4
    !cvtps2dq xmm1,xmm1 ; ry*d | by*d | ry*d | y*d
    ;RY = ( 70 * r - 59 * g - 11 * b ) *d
    ;BY = (-30 * r - 59 * g + 89 * b ) *d
    ;Y  = ( 30 * r + 59 * g + 11 * b ) *d
    
    !movdqu xmm10,xmm1
    !pshufd xmm10,xmm10,0 ; y | y | y | y
    !psrldq xmm1,4 ; 0 | ry*d | by*d | ry*d
    !movdqu xmm2,xmm1
    
    !punpckldq xmm1,xmm1 ; by | ry | by | ry
    
    !pmulld xmm1,xmm8 ; ( S * BY + C * RY ) | ( C * BY - S * RY )
    !phaddd xmm1,xmm1
    !psrad xmm1,8 ; ? | ? | byy | ryy
    !movq xmm2,xmm1
    ;RYY = ( S * BY + C * RY ) >>8;
    ;BYY = ( C * BY - S * RY ) >>8;
    
    !pmulld xmm1,xmm9
    !phaddd xmm1,xmm1
    !cvtdq2ps xmm1,xmm1
    !mulps xmm1,xmm4
    !cvtps2dq xmm1,xmm1 ; xmm1 = GYY = (-51 * RYY - 19 * BYY ) *d
    
    !mov rax,$ffffffff
    !movq xmm3,rax
    !pshufd xmm3,xmm3,$44 ; $00000000 | $ffffffff | $00000000 | $ffffffff
    !pshufd xmm2,xmm2,1 ; ryy | ryy | ryy | byy
    !pand xmm2,xmm3 ;       0 | ryy | 0   | byy
    
    !mov eax,$ffffffff
    !movd xmm3,eax
    !pand xmm1,xmm3 ; 0 | 0 | 0 | gyy
    !pslldq xmm1,4 ; 0 | 0 | gyy | 00
    
    !por xmm1,xmm2 ; 0 | ryy | gyy | byy
    
    !paddd xmm1,xmm10 ; y | ryy+y | gyy+y | byy+y
    
    !packusdw xmm1,xmm1 ; 32 -> 16
    !packuswb xmm1,xmm1 ; 16 -> 8
    
      
        !movd r10d,xmm1 ; calcul du mask
        !mov r11d,[rcx+r8*4] ; mask
        !and r10d,r11d ; modification dans le mask
        !xor r11d,$ffffffff
        !mov r12d,[rdx+r8*4] ; source
        !and r12d,r11d
        !or r12d,r10d ; ajout de la partie hors du mask
        ;!mov [rdi],r12d

    !mov [rbx+r8*4],r12d; xmm1 ; pokel
    !inc r8
    !cmp r8,[p.v_stop]
  !jb Filter_teinte_mask_saut_01

  !mov rax,[p.v_m] ; restaurtion des registres
  !mov rbx,[rax+000]
  !mov rcx,[rax+008]
  !mov rdx,[rax+016]
  !mov rdi,[rax+024]
  !mov rsi,[rax+032]
  !mov r8,[rax+040]
  !mov r9,[rax+048]
  !mov r10,[rax+056]
  !mov r11,[rax+064]
  !mov r12,[rax+072]
  !mov r13,[rax+080]
  !mov r14,[rax+088]
  !mov r15,[rax+096]
  !movdqu xmm0,[rax+104]
  !movdqu xmm1,[rax+120]
  !movdqu xmm2,[rax+136]
  !movdqu xmm3,[rax+152]
  !movdqu xmm4,[rax+168]
  !movdqu xmm5,[rax+184]
  !movdqu xmm6,[rax+200]
  !movdqu xmm7,[rax+216]
  !movdqu xmm8,[rax+232]
  !movdqu xmm9,[rax+248]
  !movdqu xmm10,[rax+264]
  !movdqu xmm11,[rax+280]
  !movdqu xmm12,[rax+296]
  !movdqu xmm13,[rax+312]
  !movdqu xmm14,[rax+328]
  !movdqu xmm15,[rax+344]
  FreeArray(Reg_memory())
  
EndProcedure


Procedure Filter_teinte(Filter_teinte_source,Filter_teinte_cible,Filter_teinte_opt,Filter_teinte_mask=0)
 
  If Filter_teinte_cible = 0 Or Filter_teinte_source = 0 : ProcedureReturn : EndIf
  Protected thread , Psource , Pcible , Pmask , lg , ht , i
  
  thread=CountCPUs(#PB_System_CPUs)
  If thread<2:thread=1:EndIf

  Protected Dim tr.q(thread)
  
  StartDrawing(ImageOutput(Filter_teinte_source))
  Psource = DrawingBuffer()
  lg = ImageWidth(Filter_teinte_source)
  ht = ImageHeight(Filter_teinte_source) 
  StopDrawing()
  
  StartDrawing(ImageOutput(Filter_teinte_cible))
  Pcible = DrawingBuffer()
  StopDrawing()
  
  If Filter_teinte_mask <> 0
    StartDrawing(ImageOutput(Filter_teinte_mask))
    Pmask = DrawingBuffer()
    StopDrawing()
  EndIf
  
  param(0)=Psource
  param(1)=Pcible
  param(2)=Pmask
  param(3)=lg
  param(4)=ht
  param(5)=thread
  param(6)= Filter_teinte_opt
  
  For i=0 To thread-1 : tr(i)=0 : Next
  For i=0 To thread-1
    While tr(i)=0   
      If Filter_teinte_mask = 0
        tr(i)=CreateThread(@Filter_teinte_thread(),i)
      Else
        tr(i)=CreateThread(@Filter_teinte_mask_thread(),i)
      EndIf
    Wend
  Next
  For i=0 To thread-1
    If IsThread(tr(i))>0 : WaitThread(tr(i)) : EndIf 
  Next
  
  FreeArray(tr())
      
EndProcedure
;-- programme test

Code : Tout sélectionner

;-- image plugins
UseGIFImageDecoder()
UseJPEG2000ImageDecoder()
UseJPEG2000ImageEncoder()
UseJPEGImageDecoder()
UseJPEGImageEncoder()
UsePNGImageDecoder()
UsePNGImageEncoder()
UseTGAImageDecoder()
UseTIFFImageDecoder()

Global Dim param(256)

;-- include files
IncludeFile "filtres\teinte.pbi"

; charge une image et la convertie en 32bit
;-------------------------------------------------------------------
Procedure load_image(nom,file$)
  Protected nom_p.i , temps_p.i , x.l , y.l , r.l,g.l,b.l , i.l
  Protected lg.l , ht.l , depth.l , temps.i  , dif.l , dif1.l

  LoadImage(nom,file$)
  If Not IsImage(nom) : ProcedureReturn 0 : EndIf
   
  StartDrawing(ImageOutput(nom))
  Depth=OutputDepth()
  StopDrawing()

  If Depth=24
    CopyImage(nom,temps)
    FreeImage(nom)
    StartDrawing(ImageOutput(temps))
    temps_p = DrawingBuffer()
    lg = ImageWidth(temps)
    ht = ImageHeight(temps)
    dif = DrawingBufferPitch() - (lg*3)
    StopDrawing()
    
  
    CreateImage(nom,lg,ht,32)
    StartDrawing(ImageOutput(nom))
    nom_p = DrawingBuffer()
    StopDrawing()
    
    For y=0 To ht-1
      For x=0 To lg-1
        i = ((y*lg)+x)*3
        r=PeekA(temps_p + i + 2 + dif1)
        g=PeekA(temps_p + i + 1 + dif1)
        b=PeekA(temps_p + i + 0 + dif1)
        PokeL(nom_p + ((y*lg)+x)*4 , r<<16 + g<<8 + b)
      Next
      dif1 = dif1 + dif
    Next
    
    FreeImage(temps) ; supprime l'image 24bits
    
  EndIf

  ProcedureReturn 1
EndProcedure
;------------------------------------------------------------------

;-- programme test
If OpenWindow(0, 0, 0, 800, 600, "Teinte", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
  
  CreateMenu(0, WindowID(0))
    MenuTitle("Load")
    MenuItem( 1, "Load Image")
   MenuTitle("Save")   
    MenuItem( 2, "Save BMP")
    ;MenuItem( 3, "Save JPG")
    MenuItem( 4, "Save Clipboard")
  MenuTitle("Quit")
    MenuItem( 5, "Quit")
  MenuTitle("mask")
    MenuItem(6,"new mask")  
    
    TrackBarGadget(10, 10, 0, 512, 20, 0, 360 )
    ;TrackBarGadget(11, 10, 20, 512, 20, 0, 6 )
    SetGadgetState(10, 0)
    
  Repeat
    update = 0
    Event = WindowEvent()
    Select Event
      Case #PB_Event_Gadget
        Select EventGadget()
          Case 10
            opt = GetGadgetState(10)
            update = 1

        EndSelect
                
      Case #PB_Event_Menu
        Select EventMenu()
          Case 1
            source = 2
            If IsImage(source) : FreeImage(source) : EndIf
            If IsImage(cible) : FreeImage(cible) : cible = 0 : EndIf
            If IsImage(mask) : FreeImage(mask) : mask = 0 : EndIf
            file$ = OpenFileRequester("Image","","",0)
            If Not Load_Image(source,file$)
              source = 0
              MessageRequester("load_image","erreur de chargement",#PB_MessageRequester_Ok | #PB_MessageRequester_Error)
            Else
              cible = 3
              If IsImage(cible) : FreeImage(cible) : EndIf
              CopyImage(source,cible)
              StartDrawing(WindowOutput(0))
              If IsImage(cible) : DrawImage(ImageID(cible),0,80) : EndIf
              StopDrawing()
              opt = GetGadgetState(10)
              update = 1
           EndIf
          
          Case 2
            nom$ = SaveFileRequester("Save BMP", "", "", 0)
            If nom$ <> "" : SaveImage(cible, nom$+".bmp" ,#PB_ImagePlugin_BMP ) : EndIf

          Case 4
            SetClipboardImage(cible)
            
          Case 5
            quit = 1
            
          Case 6
            If source <> 0
              StartDrawing(ImageOutput(source))
              Psource = DrawingBuffer()            
              lg = ImageWidth(source)            
              ht = ImageHeight(source) 
              StopDrawing()
              If IsImage(mask) : FreeImage(mask) : mask = 0 : EndIf
              mask = 4
              CreateImage(mask,lg,ht,32)
              StartDrawing(ImageOutput(mask))
              Circle(lg/2,ht/2,ht/4,$ffffff)
              Box(lg/8,ht/8,lg/6,ht/6,$ffffff)
              StopDrawing()
              opt = GetGadgetState(10)
              update = 1
            EndIf
            
        EndSelect
      EndSelect
      
      If update = 1      
      t=ElapsedMilliseconds()
      Filter_teinte(source,cible,opt,mask)

        t=ElapsedMilliseconds() - t
        
        StartDrawing(WindowOutput(0))
        If IsImage(cible)
          DrawImage(ImageID(cible),0,20)
          ;DrawText(750,5,Str(t)+"     ")
        EndIf
        StopDrawing()
      EndIf
      
      
  Until Event = #PB_Event_CloseWindow Or quit=1

  CloseWindow(0)

EndIf

Dernière modification par manababel le lun. 23/mai/2022 18:48, modifié 1 fois.
Shadow
Messages : 1304
Inscription : mer. 04/nov./2015 17:39

Re: Filtre graphique

Message par Shadow »

Salut,

J'ai un soucis avec pb version 6.00 beta 7 * 64 bits, aucune image ne peut etre chargé:

[19 :48 :18] [ERREUR] Changer la teinte d'une image 32 bit.pb (Ligne: 163)
[19 :48 :18] [ERREUR] Accès mémoire invalide. (erreur d'écriture à l'adresse 16900798)
Processeur: Intel Core I7-4790 - 4 Cœurs - 8 Thread: 3.60 Ghz.
Ram: 32 GB.
Disque: C: SDD 250 GB, D: 3 TB.
Vidéo: NVIDIA GeForce GTX 960: 2 GB DDR5.
Écran: Asus VX248 24 Pouces: 1920 x 1080.
Système: Windows 7 64 Bits.

PureBasic: 5.60 x64 Bits.
manababel
Messages : 105
Inscription : jeu. 14/mai/2020 7:40

Re: Filtre graphique

Message par manababel »

j'ai supprimé une variable qui entraînait des erreurs en mode debug.
il faut aussi activer le mode multi-thread.
Répondre