SOS Flou gausian

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Ekim
Messages : 215
Inscription : dim. 24/juin/2018 1:20

SOS Flou gausian

Message par Ekim »

Bonjours à tous :wink:

Il y aurait il une méthode plus compact et surtout moins coûteux en temps pour effectuer une telle opération s'il vous plait?
voici ci dessous mon code mais j'avoue j'ai un peu honte de son esthétique :oops:

Code : Tout sélectionner

UseJPEGImageDecoder()
UsePNGImageDecoder()


imgx=1200 
imgy=800 

TailleMax = imgx*imgy


If OpenWindow(0, 0, 0, imgx+50, imgy+50, "PixLab", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	
	pic$ = OpenFileRequester("Image indexe",pic$,"",0)
	
	If pic$ <> ""
		If LoadImage(0,pic$)
			ResizeImage(0,imgx,imgy,#PB_Image_Smooth)
			
			decal = 1
			
			If CreateImage(3,imgx,imgy,24)
				StartDrawing(ImageOutput(3))
				DrawImage(ImageID(0),0,0)
				
				For xf=0+decal To imgx-decal-1
					For yf=0+decal To imgy-decal-1
						
						a=Point(xf,yf)
						b=Point(xf-1,yf)
						c=Point(xf,yf-1)
						d=Point(xf+1,yf)
						e=Point(xf,yf+1)
						f=Point(xf-1,yf+1)
						g=Point(xf-1,yf-1)
						h=Point(xf+1,yf-1)
						i=Point(xf+1,yf+1)
						
						
						
						
						ar = Red(a)
						ag = Green(a)
						ab = Blue(a)
						
						br = Red(b)
						bg = Green(b)
						bb = Blue(b)
						
						cr = Red(c)
						cg = Green(c)
						cb = Blue(c)
						
						dr = Red(d)
						dg = Green(d)
						db = Blue(d)
						
						er = Red(e)
						eg = Green(e)
						eb = Blue(e)
						
						fr = Red(f)
						fg = Green(f)
						fb = Blue(f)
						
						gr = Red(g)
						gg = Green(g)
						gb = Blue(g)
						
						hr = Red(h)
						hg = Green(h)
						hb = Blue(h)
						
						ir = Red(i)
						ig = Green(i)
						ib = Blue(i)
						
						R = (ar+br+cr+dr+er+fr+gr+hr+ir)/9
						G = (ag+bg+cg+dg+eg+fg+gg+hg+ig)/9
						B = (ab+bb+cb+db+eb+fb+gb+hb+ib)/9
						
						
						
						
						If R > 255:R = 255:EndIf
						If R < 0:R = 0:EndIf
						
						If G > 255:G = 255:EndIf
						If G < 0:G = 0:EndIf
						
						If B > 255:B = 255:EndIf
						If B < 0:B = 0:EndIf
						
						Plot(xf,yf,RGB(R,G,B))
						
					Next yf	
				Next xf
				StopDrawing() 
				
				ImageGadget(0, 0, 0, imgx, imgy, ImageID(3))
			EndIf
		Else
			Debug "Erreur de chargement"
		EndIf
	EndIf
	
	Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf


:P
Avatar de l’utilisateur
Ar-S
Messages : 9540
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: SOS Flou gausian

Message par Ar-S »

Salut Ekim.
Tu peux trouver toute une lib (avec sources) d'FX ici : https://github.com/pbcodex/ImageFilter
Ensuite un code (bien violent) pour faire du blur vitesse grand V sur un sprite (donc adaptable pour une image) ici : https://www.purebasic.fr/english/viewto ... 16&t=73777

Une solution plus accessible ici : https://www.purebasic.fr/english/viewto ... ur#p505099

Avec les 2 .PBI fournis (kernels3x3 et convolutionfilter) ton exemple donnerait ça :

Code : Tout sélectionner

XIncludeFile("ConvolutionFilter.pbi")


UseJPEGImageDecoder()
UsePNGImageDecoder()


width=1200
height=800


If OpenWindow(0, 0, 0, width+50, height+50, "PixLab", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
  ;1 On charge
  Imgfile$ = OpenFileRequester("Image indexe",Imgfile$,"",0)
  hImg1 = LoadImage(#PB_Any, Imgfile$)
  If Not hImg1
    MessageRequester("Error","Couldnt load " + Imgfile$):  End
  EndIf
  
  ResizeImage(hImg1,width,height,#PB_Image_Smooth)

  
  ;2 - Initialisation de la matrice 3x3
  blur2 = #K3x3_GAUSSIANBLUR_2
  
  If Not LoadKernel3x3(kernelid, blur2): MessageRequester("Error","Invalid kernel id"): End: EndIf
  
  ;3. Create convolution filtered image. Convolution filters like these cannot modify the
  ;   original without adversely distorting the result, so they must output to a 2nd image.
  hImg2 = ConvolutionFilterImage(hImg1)
  
  
  
  ImageGadget(0, 0, 0, imgx, imgy, ImageID(hImg2))
  

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Enfin, je viens de trouver une approche très intéressante qui, au lieu d'utiliser une matrice 3x3, applique une moyenne horizontal puis verticale ce qui amène au même résultat plus rapidement.
https://www.youtube.com/watch?v=Vi94GhaHpz0
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Ekim
Messages : 215
Inscription : dim. 24/juin/2018 1:20

Re: SOS Flou gausian

Message par Ekim »

Merci @Ar-S pour ton aide et la démonstration, c'est très intéressant :wink:

Il y a des moments où il ne faut pas chercher à essayé de comprendre le code car hyper compliqué :lol:

notamment l'avant dernier lien, il est tout simplement flippant 8O
manababel
Messages : 144
Inscription : jeu. 14/mai/2020 7:40

Re: SOS Flou gausian

Message par manababel »

Bonjour , je suis nouveau sur ce forum

Si ca vous intéresse toujour , voici 3 programmes pour faire un flou plus rapide que le vôtre .

Le programme "sp1" , est le même que le vôtre, mais en utilise des "pointeurs" a la place de "point et "plot" , et des multiplications a la place de divisions.

Le programme "sp2" est une façon beaucoup plus rapide de faire un flou , mais le résultât est moins propre
(en modifiant ce programme , on peu se rapprocher d'un flou gaussian )

Le programme "sp3" est le même que le programme sp1 mais "threadé" . ( Je ne maîtrise pas les threads. )

une méthode plus rapide serai d'utiliser le language "assembleur".
la méthode la plus rapide est d'utiliser la carte graphique ("shaders").



Code : Tout sélectionner

;-------------------------------------------------------------------------------
UseJPEGImageDecoder()
UsePNGImageDecoder()

Global Dim thread_param(1024)
Global Dim param(1030)

Macro rgbreturn(var,r,g,b)
  r=(var & $ff0000)>>16
  g=(var & $00ff00)>>8
  b=(var & $0000ff)
EndMacro




;convolution      
Procedure sp1(source,cible,opt=1)
  
  If opt<1:opt=1:EndIf
  If opt>5:opt=5:EndIf
  
  ht = ImageHeight(source) 
  lg = ImageWidth(source)
  
  StartDrawing(ImageOutput(souce))
  source=DrawingBuffer()
  bit=OutputDepth()
  StopDrawing()

  StartDrawing(ImageOutput(cible))
  cible=DrawingBuffer()
  StopDrawing()
  
  m=4
  If bit=24 : m=3 : EndIf
  ht4=lg*m
  div.f=1/((opt*2+1) * (opt*2+1))
  
  For y=opt To ht-1-opt
    For x=opt To lg-1-opt
      r=0
      g=0
      b=0
      For dy=-opt To opt
        For dx=-opt To opt
          pos=source + (( (y+dy) * lg ) + (x+dx) ) * m
          var=PeekL(pos)
          b=b+(var & $ff0000)>>16
          g=g+(var & $00ff00)>>8
          r=r+(var & $0000ff)
        Next
      Next
      r=r*div
      g=g*div
      b=b*div
      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

      pos=cible + (( y * lg ) + x ) << 2
      PokeL(pos,RGB(r,g,b))
    Next  
  Next
          
EndProcedure


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


; boxblur
 Procedure sp2(source,cible,opt=1)

  If opt<1:opt=1:EndIf
  
  ht = ImageHeight(source) 
  lg = ImageWidth(source)
  
  StartDrawing(ImageOutput(souce))
  source=DrawingBuffer()
  bit=OutputDepth()
  StopDrawing()

  StartDrawing(ImageOutput(cible))
  cible=DrawingBuffer()
  StopDrawing()
  
  m=4
  If bit=24 : m=3 : EndIf
  ht4=lg*m
  
cible2=AllocateMemory((lg*ht*4),#PB_Memory_NoClear) 

  d.f=1/(opt+opt+1)
  For y=0 To ht-1
    pos=source+(lg*y*m)
    
    r=0:g=0:b=0
    For x=0 To (opt*2)
      var=PeekL(pos+x*m)
      RGBReturn(var,r1,g1,b1)  
      r=r+r1
      g=g+g1
      b=b+b1
    Next
    r2=r:g2=g:b2=b
    For x=opt To 0 Step -1
      var=PeekL(pos+(x+opt)*m)
      RGBReturn(var,r1,g1,b1)
      r=r-r1
      g=g-g1
      b=b-b1
      d2.f=1/(x+opt)
      r1=r*d2
      g1=g*d2
      b1=b*d2
      PokeL(cible2+(lg*y+x)*4,(r1<<16)+(g1<<8)+b1)
    Next
    
    r=r2:g=g2:b=b2
    For x=opt+1 To lg-opt-1
      var=PeekL(pos+(x-opt-1)*m)
      RGBReturn(var,r1,g1,b1)
      var=PeekL(pos+(x+opt)*m)
      RGBReturn(var,r2,g2,b2)
      r=r-r1+r2
      g=g-g1+g2
      b=b-b1+b2
      r1=r*d
      g1=g*d
      b1=b*d
      PokeL(cible2+(lg*y+x)*4,(r1<<16)+(g1<<8)+b1)
    Next 
    
    r=0:g=0:b=0
    For x=lg-(opt*2) To lg-1
      var=PeekL(pos+x*m)
      RGBReturn(var,r1,g1,b1)  
      r=r+r1
      g=g+g1
      b=b+b1
    Next
    compt=opt-1
    For x=lg-opt To lg-1
      var=PeekL(pos+(x-opt)*m)
      RGBReturn(var,r1,g1,b1)
      r=r-r1
      g=g-g1
      b=b-b1
      d2.f=1/(compt+opt)
      r1=r*d2
      g1=g*d2
      b1=b*d2
      PokeL(cible2+(lg*y+x)*4,(r1<<16)+(g1<<8)+b1)
      compt=compt-1
    Next
  Next
  
;******************************  
  source=cible2   
  For x=0 To lg-1
    
    r=0:g=0:b=0
    For y=0 To (opt*2)
      var=PeekL(source+(y*lg+x)*4)
      RGBReturn(var,r1,g1,b1)  
      r=r+r1
      g=g+g1
      b=b+b1
    Next
    r2=r:g2=g:b2=b
    For y=opt To 0 Step -1
      var=PeekL(source+(y*lg+x)*4)
      RGBReturn(var,r1,g1,b1)
      r=r-r1
      g=g-g1
      b=b-b1
      d2.f=1/(y+opt)
      r1=r*d2
      g1=g*d2
      b1=b*d2
      PokeL(cible+(lg*y+x)*4,(r1<<16)+(g1<<8)+b1)
    Next
    
    r=r2:g=g2:b=b2
    For y=opt+1 To ht-opt-1
      var=PeekL(source+((y-opt-1)*lg+x)*4)
      RGBReturn(var,r1,g1,b1)
      var=PeekL(source+((y+opt)*lg+x)*4)
      RGBReturn(var,r2,g2,b2)
      r=r-r1+r2
      g=g-g1+g2
      b=b-b1+b2
      r1=r*d
      g1=g*d
      b1=b*d
      PokeL(cible+(lg*y+x)*4,(r1<<16)+(g1<<8)+b1)
    Next 
    
    r=0:g=0:b=0
    For y=ht-(opt*2) To ht-1
      var=PeekL(source+(lg*y+x)*4)
      RGBReturn(var,r1,g1,b1)  
      r=r+r1
      g=g+g1
      b=b+b1
    Next
    compt=opt-1
    For y=ht-opt To ht-1
      var=PeekL(source+((y-opt)*lg+x)*4)
      RGBReturn(var,r1,g1,b1)
      r=r-r1
      g=g-g1
      b=b-b1
      d2.f=1/(compt+opt)
      r1=r*d2
      g1=g*d2
      b1=b*d2
      PokeL(cible+(lg*y+x)*4,(r1<<16)+(g1<<8)+b1)
      compt=compt-1
    Next
  Next
      
  FreeMemory(cible2)        
  
 EndProcedure
 
 
 
 ;------------------------------------------------------------------------------- 
 
 
 Procedure sp1_thread(i)
  
   source=param(0)
   cible=param(1)
   lg=param(2)
   ht=param(3)
   
   ht2=param(4)
   start=ht2*i
   stop=start+ht2
   
   m=param(5)
   ht4=param(6)
   opt=param(7)
   div.f=1/ ( ((opt*2)+1) * ((opt*2)+1) )
   

  For y=start To stop
    If y>opt And y<ht-1-opt
      For x=opt To lg-1-opt
        r=0
        g=0
        b=0
        For dy=-opt To opt
          For dx=-opt To opt
            px=x+dx
            py=y+dy
            If px<0:Debug "px":EndIf
            If py<0:Debug "py":EndIf
            pos=source + (( py * lg ) + px ) * m
            var=PeekL(pos)
            b=b+(var & $ff0000)>>16
            g=g+(var & $00ff00)>>8
            r=r+(var & $0000ff)
          Next
        Next
        r=r*div
        g=g*div
        b=b*div
        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
  
        pos=cible + (( y * lg ) + x ) << 2
        PokeL(pos,RGB(r,g,b))
      Next 
    EndIf
  Next     
EndProcedure

          
 
 Procedure sp3(source,cible,opt=1)
   
   If opt<1:opt=1:EndIf
   If opt>5:opt=5:EndIf
   
 thread=CountCPUs(#PB_System_CPUs)
 If thread<2:thread=1:EndIf
 ;thread=8
  ht = ImageHeight(source) 
  lg = ImageWidth(source)
  
  StartDrawing(ImageOutput(souce))
  source=DrawingBuffer()
  bit=OutputDepth()
  StopDrawing()

  StartDrawing(ImageOutput(cible))
  cible=DrawingBuffer()
  StopDrawing()
  
  m=4
  If bit=24 : m=3 : EndIf
  ht4=lg*m
  
    Dim tr.q(thread)
    
    param(0)=source
    param(1)=cible
    param(2)=lg
    param(3)=ht
    param(4)=ht/thread
    param(5)=m
    param(6)=ht4
    param(7)=opt
    
    tr(i)=0
    For i=0 To thread-1
      While tr(i)=0
        tr(i)=CreateThread(@sp1_thread(),i)
      Wend
    Next
    
    For i=0 To thread-1
     If IsThread(tr(i))>0
       WaitThread(tr(i))
     EndIf  
    Next
    
    ; ajouter un thread si (ht / thread)<>1
    
    FreeArray(tr())
    FreeArray(param())
    
  EndProcedure
  
 ;-------------------------------------------------------------------------------
  
  
imgx=1200
imgy=800
          
If OpenWindow(0, 0, 0, imgx+50, imgy+50, "PixLab", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
   
   pic$ = OpenFileRequester("Image indexe",pic$,"",0)
   
   source=0
   cible=1
   If pic$ <> ""
     If LoadImage(source,pic$)
       ResizeImage(source,imgx,imgy,#PB_Image_Smooth)
     EndIf
   EndIf
   
   CreateImage(cible,imgx,imgy,32)
   
   
   t.q=ElapsedMilliseconds()
   sp1(source,cible,5)
   t1.q=ElapsedMilliseconds()-t
   
   t.q=ElapsedMilliseconds()
   sp2(source,cible,5)
   t2.q=ElapsedMilliseconds()-t
   
   t.q=ElapsedMilliseconds()
   sp3(source,cible,5)
   t3.q=ElapsedMilliseconds()-t
   
   ;ImageGadget(0, 0, 0, imgx, imgy, ImageID(cible))
   
   StartDrawing(WindowOutput(0))
   DrawImage(ImageID(cible),0,0)
   DrawText(5,5,Str(t1))
   DrawText(5,25,Str(t2))
   DrawText(5,45,Str(t3))
   StopDrawing()
   
   
   Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
 EndIf
 
 ;-------------------------------------------------------------------------------
Avatar de l’utilisateur
Ar-S
Messages : 9540
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: SOS Flou gausian

Message par Ar-S »

Bonjour et bienvenue manababel.
La seconde routine est vraiment efficace.
Merci pour ce partage.
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Avatar de l’utilisateur
Guillot
Messages : 672
Inscription : jeu. 25/juin/2015 16:18

Re: SOS Flou gausian

Message par Guillot »

super code manababel

j'espere que tu va nous en montrer d'autres !
manababel
Messages : 144
Inscription : jeu. 14/mai/2020 7:40

Re: SOS Flou gausian

Message par manababel »

Voici la version modifier du programme sp2

Il est plus lent, car le programme est appelé plusieurs fois ,
mais reste plus rapide que la version "sp1".
Et le résultat visuel est beaucoup plus proche d'un flou "gaussian"

Je me suis basé sur le cite suivant pour faire se programme .

http://blog.ivank.net/fastest-gaussian-blur.html


Code : Tout sélectionner

Procedure Copy24(source,cible,taille)
  EnableASM 
      !mov rsi,[p.v_source]
      !mov rdi,[p.v_cible]
      !mov rbx,[p.v_taille]
      !shr rbx,2
      !copy_boucle24:
        !mov eax,[rsi]      
        !mov [rdi],eax
        !add rsi,3
        !add rdi,4
        !dec rbx
       !jnz copy_boucle24
  DisableASM   
  
  var=Mod(taille,4)
  If var=0:ProcedureReturn:EndIf
  For i=0 To var-1
    PokeL(cible+i<<2,PeekL(source+i<<2))
  Next
  
EndProcedure 
  
Procedure Copy32(source,cible,taille)
  EnableASM 
      !mov rsi,[p.v_source]
      !mov rdi,[p.v_cible]
      !mov rbx,[p.v_taille]
      !xor rcx,rcx
      !shr rbx,4
      !copy_boucle:
        !movaps xmm0,[rsi+rcx]      
        !movntps [rdi+rcx],xmm0
        !add rcx,16
        !dec rbx
      !jnz copy_boucle
  DisableASM   
  
  var=Mod(taille,4)
  If var=0:ProcedureReturn:EndIf
  For i=0 To var-1
    PokeL(cible+i<<2,PeekL(source+i<<2))
  Next
  
EndProcedure 
  
  Procedure boxBlurH(source, cible, lg, ht, opt)

  d.f=1/(opt+opt+1)
  For y=0 To ht-1
    pos=source+(lg*y*4)
    
    r=0:g=0:b=0
    For x=0 To (opt*2)
      var=PeekL(pos+x*4)
      RGBReturn(var,r1,g1,b1)  
      r=r+r1
      g=g+g1
      b=b+b1
    Next
    r2=r:g2=g:b2=b
    For x=opt To 0 Step -1
      var=PeekL(pos+(x+opt)*4)
      RGBReturn(var,r1,g1,b1)
      r=r-r1
      g=g-g1
      b=b-b1
      d2.f=1/(x+opt)
      r1=r*d2
      g1=g*d2
      b1=b*d2
      PokeL(cible+(lg*y+x)*4,(r1<<16)+(g1<<8)+b1)
    Next
    
    r=r2:g=g2:b=b2
    For x=opt+1 To lg-opt-1
      var=PeekL(pos+(x-opt-1)*4)
      RGBReturn(var,r1,g1,b1)
      var=PeekL(pos+(x+opt)*4)
      RGBReturn(var,r2,g2,b2)
      r=r-r1+r2
      g=g-g1+g2
      b=b-b1+b2
      r1=r*d
      g1=g*d
      b1=b*d
      PokeL(cible+(lg*y+x)*4,(r1<<16)+(g1<<8)+b1)
    Next 
    
    r=0:g=0:b=0
    For x=lg-(opt*2) To lg-1
      var=PeekL(pos+x*4)
      RGBReturn(var,r1,g1,b1)  
      r=r+r1
      g=g+g1
      b=b+b1
    Next
    compt=opt-1
    For x=lg-opt To lg-1
      var=PeekL(pos+(x-opt)*4)
      RGBReturn(var,r1,g1,b1)
      r=r-r1
      g=g-g1
      b=b-b1
      d2.f=1/(compt+opt)
      r1=r*d2
      g1=g*d2
      b1=b*d2
      PokeL(cible+(lg*y+x)*4,(r1<<16)+(g1<<8)+b1)
      compt=compt-1
    Next
  Next
  
EndProcedure
 
Procedure boxBlurT(source, cible, lg, ht, opt)
  
  d.f=1/(opt+opt+1)
  For x=0 To lg-1
    
    r=0:g=0:b=0
    For y=0 To (opt*2)
      var=PeekL(source+(y*lg+x)*4)
      RGBReturn(var,r1,g1,b1)  
      r=r+r1
      g=g+g1
      b=b+b1
    Next
    r2=r:g2=g:b2=b
    For y=opt To 0 Step -1
      var=PeekL(source+(y*lg+x)*4)
      RGBReturn(var,r1,g1,b1)
      r=r-r1
      g=g-g1
      b=b-b1
      d2.f=1/(y+opt)
      r1=r*d2
      g1=g*d2
      b1=b*d2
      PokeL(cible+(lg*y+x)*4,(r1<<16)+(g1<<8)+b1)
    Next
    
    r=r2:g=g2:b=b2
    For y=opt+1 To ht-opt-1
      var=PeekL(source+((y-opt-1)*lg+x)*4)
      RGBReturn(var,r1,g1,b1)
      var=PeekL(source+((y+opt)*lg+x)*4)
      RGBReturn(var,r2,g2,b2)
      r=r-r1+r2
      g=g-g1+g2
      b=b-b1+b2
      r1=r*d
      g1=g*d
      b1=b*d
      PokeL(cible+(lg*y+x)*4,(r1<<16)+(g1<<8)+b1)
    Next 
    
    r=0:g=0:b=0
    For y=ht-(opt*2) To ht-1
      var=PeekL(source+(lg*y+x)*4)
      RGBReturn(var,r1,g1,b1)  
      r=r+r1
      g=g+g1
      b=b+b1
    Next
    compt=opt-1
    For y=ht-opt To ht-1
      var=PeekL(source+((y-opt)*lg+x)*4)
      RGBReturn(var,r1,g1,b1)
      r=r-r1
      g=g-g1
      b=b-b1
      d2.f=1/(compt+opt)
      r1=r*d2
      g1=g*d2
      b1=b*d2
      PokeL(cible+(lg*y+x)*4,(r1<<16)+(g1<<8)+b1)
      compt=compt-1
    Next
  Next

  EndProcedure
  
Procedure boxBlur_4 (source, cible, lg, ht, r)
  copy32(source,cible,lg*ht*4)
  boxblurT(cible,source,lg,ht,r)
  boxBlurH(source,cible,lg,ht,r)
EndProcedure


;--GaussBlur : http://blog.ivank.net/fastest-gaussian-blur.html
Procedure sp4(source,cible,r)
  
  If r<1:r=1:EndIf
  
  ht = ImageHeight(source) 
  lg = ImageWidth(source)
  
  StartDrawing(ImageOutput(souce))
  source=DrawingBuffer()
  bit=OutputDepth()
  StopDrawing()

  StartDrawing(ImageOutput(cible))
  cible=DrawingBuffer()
  StopDrawing()
  
  source2=AllocateMemory((lg*ht*4))
  If bit=32
    copy32(source,source2,lg*ht*4)
  Else
    copy24(source,source2,lg*ht*4)
  EndIf
  

  ; r est à modifier pour avoir de meilleurs resultats.
  
  boxBlur_4(source2, cible, lg, ht, r)
  boxBlur_4(cible, source2, lg, ht, r)
  boxBlur_4(source2, cible, lg, ht, r)
  
  FreeMemory(source2)
 
  EndProcedure
Avatar de l’utilisateur
Zorro
Messages : 2186
Inscription : mar. 31/mai/2016 9:06

Re: SOS Flou gausian

Message par Zorro »

Salut,

peut etre le plus rapide, en tout cas le plus court, c'est ceci ;)

Code : Tout sélectionner


;***********************************************
;Titre  :*flou_test
;Auteur  : Dobro
;Date  :16/05/2020
;Heure  :09:33:54
;Version Purebasic :  PureBasic 5.71 LTS (Windows - x86)
;Version de l'editeur :EPB PHOENIX V2.68
; Libairies necessaire : Aucune 
;***********************************************

UseJPEGImageDecoder()
UsePNGImageDecoder()

Enumeration
		#Win 
		#source		
EndEnumeration

imgx=800
imgy=600



If OpenWindow(#win, 0, 0, imgx+50, imgy+50, "PixLab", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)		
		pic$ = OpenFileRequester("Image indexe",pic$,"",0)		
		If pic$ <> ""
				If LoadImage(#source,pic$)
						ResizeImage(#source,imgx/8,imgy/8,#PB_Image_Smooth  )	; plus on reduit, plus le flou sera fort <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
							ResizeImage(#source,imgx,imgy,#PB_Image_Smooth)		
						StartDrawing(WindowOutput(#win))
								DrawImage(ImageID(#source),0,0) 
						StopDrawing()
				EndIf
				
		EndIf
		Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf

Avatar de l’utilisateur
Ar-S
Messages : 9540
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: SOS Flou gausian

Message par Ar-S »

Ahah ce cheater :mrgreen:
Là tu nous pixelises l'image, c'est hyper moins propre qu'un floue gaussien. Même si on divise seulement par 2 c'est super "aliasé"
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
manababel
Messages : 144
Inscription : jeu. 14/mai/2020 7:40

Re: SOS Flou gausian

Message par manababel »

Zoro, j'aime bien ce genre de "bidouille", mais le résultat et beaucoup trop différent de ce qui est demandé

Peut-être qu'un mix de nos méthodes pourrait donner un résultat acceptable.

Voici une nouvelle version . Les boucles principales ont été réécrites en assambleur (simd) .
Le gain obtenu est très appréciable.

ps : utiliser "push/pop" pour sauvegarder les registres fait "planter" le programme.


Code : Tout sélectionner

UseJPEGImageDecoder()
UsePNGImageDecoder()

Macro rgbreturn(var,r,g,b)
  r=(var & $ff0000)>>16
  g=(var & $00ff00)>>8
  b=(var & $0000ff)
EndMacro  
  
Procedure Copy24(source,cible,taille)
  EnableASM
      !mov rsi,[p.v_source]
      !mov rdi,[p.v_cible]
      !mov rbx,[p.v_taille]
      !shr rbx,2
      !copy_boucle24:
        !mov eax,[rsi]     
        !mov [rdi],eax
        !add rsi,3
        !add rdi,4
        !dec rbx
       !jnz copy_boucle24
  DisableASM   
 
  var=Mod(taille,4)
  If var=0:ProcedureReturn:EndIf
  For i=0 To var-1
    PokeL(cible+i<<2,PeekL(source+i<<2))
  Next
 
EndProcedure
 
Procedure Copy32(source,cible,taille)
  EnableASM
      !mov rsi,[p.v_source]
      !mov rdi,[p.v_cible]
      !mov rbx,[p.v_taille]
      !xor rcx,rcx
      !shr rbx,4
      !copy_boucle:
        !movaps xmm0,[rsi+rcx]     
        !movntps [rdi+rcx],xmm0
        !add rcx,16
        !dec rbx
      !jnz copy_boucle
  DisableASM   
 
  var=Mod(taille,4)
  If var=0:ProcedureReturn:EndIf
  For i=0 To var-1
    PokeL(cible+i<<2,PeekL(source+i<<2))
  Next
 
EndProcedure
 
Procedure boxBlurH(source, cible, lg, ht, opt)
  
  Dim pix.l(12)
  np=@pix()
  
  d.f=1/(opt+opt+1)
  For y=0 To ht-1
    pos=source+(lg*y*4)
    
    r=0:g=0:b=0
    For x=0 To (opt*2)
      var=PeekL(pos+x*4)
      RGBReturn(var,r1,g1,b1)  
      r=r+r1
      g=g+g1
      b=b+b1
    Next
    r2=r:g2=g:b2=b
    For x=opt To 0 Step -1
      var=PeekL(pos+(x+opt)*4)
      RGBReturn(var,r1,g1,b1)
      r=r-r1
      g=g-g1
      b=b-b1
      d2.f=1/(x+opt)
      r1=r*d2
      g1=g*d2
      b1=b*d2
      PokeL(cible+(lg*y+x)*4,(r1<<16)+(g1<<8)+b1)
    Next
    
    ;r=r2:g=g2:b=b2
    ;For x=opt+1 To lg-opt-1
      ;var=PeekL(pos+(x-opt-1)*4)
      ;RGBReturn(var,r1,g1,b1)
      ;var=PeekL(pos+(x+opt)*4)
      ;RGBReturn(var,r2,g2,b2)
      ;r=r-r1+r2
      ;g=g-g1+g2
      ;b=b-b1+b2
      ;r1=r*d
      ;g1=g*d
      ;b1=b*d
      ;PokeL(cible+(lg*y+x)*4,(r1<<16)+(g1<<8)+b1)
      ;Next
    
    pos=source+(lg*y*4)
    pix(0)=b2:pix(1)=g2:pix(2)=r2
    x=opt+1
    var1=(pos+(x-opt-1)*4)
    var2=(pos+(x+opt)*4)
    var3=(cible+(lg*y+x)*4)
    EnableASM
    !mov r10,[p.v_var1]
    !mov r11,[p.v_var2]
    !mov r12,[p.v_var3]
    !pxor xmm15,xmm15
    !VPBROADCASTD xmm14,[p.v_d]
    !mov rax,[p.v_np]
    !movdqu xmm3,[rax]
    !mov rcx,[p.v_opt] ;For x=opt+1 
    !inc rcx
    !mov rdx,[p.v_lg] ;To lg-opt-1
    !sub rdx,[p.v_opt]
    !dec rdx
    
    !boxBlurH_saut1:
      !movd xmm1,[r10]  ;var=PeekL(pos+(x-opt-1)*4)
      !punpcklbw xmm1,xmm15 ;RGBReturn(var,r1,g1,b1)
      !punpcklwd xmm1,xmm15
      !movd xmm2,[r11]  ;var=PeekL(pos+(x+opt)*4)
      !punpcklbw xmm2,xmm15 ;RGBReturn(var,r2,g2,b2)
      !punpcklwd xmm2,xmm15
      !psubd xmm3,xmm1 ; r=r-r1
      !paddd xmm3,xmm2 ; r=r+r2
      !movdqu xmm0,xmm3
      !cvtdq2ps xmm0,xmm0 ; r1.f = float r1
      !mulps xmm0,xmm14 ;r1=r*d  : d = 1/(opt+opt+1)
      !cvtps2dq xmm0,xmm0 ; r1.L = int r1
      !packusdw xmm0,xmm15
      !packuswb xmm0,xmm15
      !movd [r12],xmm0 ;PokeL(cible+(lg*y+x)*4,(r1<<16)+(g1<<8)+b1)
      !add r10,4
      !add r11,4
      !add r12,4
      !inc rcx
      !cmp rcx,rdx
    !jbe boxBlurH_saut1
    DisableASM  
    
    r=0:g=0:b=0
    For x=lg-(opt*2) To lg-1
      var=PeekL(pos+x*4)
      RGBReturn(var,r1,g1,b1)  
      r=r+r1
      g=g+g1
      b=b+b1
    Next
    compt=opt-1
    For x=lg-opt To lg-1
      var=PeekL(pos+(x-opt)*4)
      RGBReturn(var,r1,g1,b1)
      r=r-r1
      g=g-g1
      b=b-b1
      d2.f=1/(compt+opt)
      r1=r*d2
      g1=g*d2
      b1=b*d2
      PokeL(cible+(lg*y+x)*4,(r1<<16)+(g1<<8)+b1)
      compt=compt-1
    Next
  Next
  FreeArray(pix())
EndProcedure

Procedure boxBlurT(source, cible, lg, ht, opt)
 
  Dim pix.l(12)
  np=@pix()
  d.f=1/(opt+opt+1)
  For x=0 To lg-1
    
    r=0:g=0:b=0
    For y=0 To (opt*2)
      var=PeekL(source+(y*lg+x)*4)
      RGBReturn(var,r1,g1,b1)  
      r=r+r1
      g=g+g1
      b=b+b1
    Next
    r2=r:g2=g:b2=b
    For y=opt To 0 Step -1
      var=PeekL(source+(y*lg+x)*4)
      RGBReturn(var,r1,g1,b1)
      r=r-r1
      g=g-g1
      b=b-b1
      d2.f=1/(y+opt)
      r1=r*d2
      g1=g*d2
      b1=b*d2
      PokeL(cible+(lg*y+x)*4,(r1<<16)+(g1<<8)+b1)
    Next
    
    ;r=r2:g=g2:b=b2
    ;For y=opt+1 To ht-opt-1
      ;var=PeekL(source+((y-opt-1)*lg+x)*4)
      ;RGBReturn(var,r1,g1,b1)
      ;var=PeekL(source+((y+opt)*lg+x)*4)
      ;RGBReturn(var,r2,g2,b2)
      ;r=r-r1+r2
      ;g=g-g1+g2
      ;b=b-b1+b2
      ;r1=r*d
      ;g1=g*d
      ;b1=b*d
      ;PokeL(cible+(lg*y+x)*4,(r1<<16)+(g1<<8)+b1)
    ;Next 
    
    pix(0)=b2:pix(1)=g2:pix(2)=r2
    y=opt+1
    var1=(source+((y-opt-1)*lg+x)*4)
    var2=(source+((y+opt)*lg+x)*4)
    var3=(cible+(lg*y+x)*4)
    var4=lg*4
    EnableASM
    !mov r10,[p.v_var1]
    !mov r11,[p.v_var2]
    !mov r12,[p.v_var3]
    !mov r13,[p.v_var4]
    !pxor xmm15,xmm15
    !VPBROADCASTD xmm14,[p.v_d]
    !mov rax,[p.v_np]
    !movdqu xmm3,[rax]
    !mov rcx,[p.v_opt] ;For y=opt+1 
    !inc rcx
    !mov rdx,[p.v_ht] ;to ht-opt-1
    !sub rdx,[p.v_opt]
    !dec rdx
    
    !boxBlurT_saut1:
      !movd xmm1,[r10]  ;var=PeekL(pos+(x-opt-1)*4)
      !punpcklbw xmm1,xmm15 ;RGBReturn(var,r1,g1,b1)
      !punpcklwd xmm1,xmm15
      !movd xmm2,[r11]  ;var=PeekL(pos+(x+opt)*4)
      !punpcklbw xmm2,xmm15 ;RGBReturn(var,r2,g2,b2)
      !punpcklwd xmm2,xmm15
      !psubd xmm3,xmm1 ; r=r-r1
      !paddd xmm3,xmm2 ; r=r+r2
      !movdqu xmm0,xmm3
      !cvtdq2ps xmm0,xmm0
      !mulps xmm0,xmm14 ;r1=r*d  : d = 1/(opt+opt+1)
      !cvtps2dq xmm0,xmm0
      !packusdw xmm0,xmm15
      !packuswb xmm0,xmm15
      !movd [r12],xmm0 ;PokeL(cible+(lg*y+x)*4,(r1<<16)+(g1<<8)+b1)
      !add r10,r13
      !add r11,r13
      !add r12,r13
      !inc rcx
      !cmp rcx,rdx
    !jbe boxBlurT_saut1
    DisableASM  
    
    r=0:g=0:b=0
    For y=ht-(opt*2) To ht-1
      var=PeekL(source+(lg*y+x)*4)
      RGBReturn(var,r1,g1,b1)  
      r=r+r1
      g=g+g1
      b=b+b1
    Next
    compt=opt-1
    For y=ht-opt To ht-1
      var=PeekL(source+((y-opt)*lg+x)*4)
      RGBReturn(var,r1,g1,b1)
      r=r-r1
      g=g-g1
      b=b-b1
      d2.f=1/(compt+opt)
      r1=r*d2
      g1=g*d2
      b1=b*d2
      PokeL(cible+(lg*y+x)*4,(r1<<16)+(g1<<8)+b1)
      compt=compt-1
    Next
  Next
  FreeArray(pix())
  EndProcedure
 
Procedure boxBlur_4 (source, cible, lg, ht, r)
  copy32(source,cible,lg*ht*4)
  boxblurT(cible,source,lg,ht,r)
  boxBlurH(source,cible,lg,ht,r)
EndProcedure


;--GaussBlur : http://blog.ivank.net/fastest-gaussian-blur.html
Procedure sp4(source,cible,r)
 
  If r<1:r=1:EndIf
 
  ht = ImageHeight(source)
  lg = ImageWidth(source)
 
  StartDrawing(ImageOutput(souce))
  source=DrawingBuffer()
  bit=OutputDepth()
  StopDrawing()

  StartDrawing(ImageOutput(cible))
  cible=DrawingBuffer()
  StopDrawing()
  
  If lg>ht
    If r>=(ht/2):r=(ht/2)-1:EndIf
  Else
    If r>=(lg/2):r=(lg/2)-1:EndIf
  EndIf
  
  source2=AllocateMemory((lg*ht*4))
  If bit=32
    copy32(source,source2,lg*ht*4)
  Else
    copy24(source,source2,lg*ht*4)
  EndIf
 
  ; r est à modifier pour avoir de meilleurs resultats.
 
  boxBlur_4(source2, cible, lg, ht, r)
  boxBlur_4(cible, source2, lg, ht, r)
  boxBlur_4(source2, cible, lg, ht, r)
  
  FreeMemory(source2)

  EndProcedure
  
  
  

  
imgx=1200
imgy=800
         
If OpenWindow(0, 0, 0, imgx+50, imgy+50, "PixLab", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
   
   pic$ = OpenFileRequester("Image indexe",pic$,"",0)
   
   source=0
   cible=1
   If pic$ <> ""
     If LoadImage(source,pic$)
       ResizeImage(source,imgx,imgy,#PB_Image_Smooth)
     EndIf
   EndIf
   
   CreateImage(cible,imgx,imgy,32)
   
   t.q=ElapsedMilliseconds()
   sp4(source,cible,15)
   t.q=ElapsedMilliseconds()-t
      
   StartDrawing(WindowOutput(0))
   DrawImage(ImageID(cible),0,0)
   DrawText(5,5,Str(t))

   StopDrawing()
   
   
   Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Avatar de l’utilisateur
Guillot
Messages : 672
Inscription : jeu. 25/juin/2015 16:18

Re: SOS Flou gausian

Message par Guillot »

j'ai comparé : 5 fois plus rapide !!
(en revanche ça ne fonctionne pas avec toute les resolutions horizontale)
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: SOS Flou gausian

Message par Ollivier »

manababel a écrit :ps : utiliser "push/pop" pour sauvegarder les registres fait "planter" le programme.
Euh... Y'aurait moyen que tu les places en commentaires ? Ça permet de voir où elles sont placées, et donc pourquoi ça se mettrait à planter. Sûr il y a une raison.
manababel
Messages : 144
Inscription : jeu. 14/mai/2020 7:40

Re: SOS Flou gausian

Message par manababel »

J'ai fait une vingtaine de tests avec des résolutions finissant de 0 à 9 , je n'ai pas eu de problèmes.
Pouvez-vous me donner les révolutions qui posent problème ?


Normalement, en assembleur, il faut sauvegarder tous les registres que l'on va modifier puis les rétablir à la fin du programme, pour éviter d'interagir avec d'autres programmes en cours.
Il est plus simple et facile d'utiliser "push" et "pop" pour ça.
Il est tout aussi possible de sauvegarder registres dans des variables.
Ses commandes se placent juste après "ENABLEASM" et juste avant "DISABLEASM"


Il y a une faute de frappe dans le dernier programme posté.
Dans la procédure sp4()
Il y a "StartDrawing(ImageOutput(souce))"
Il faut remplacer "souce" par "source"
Demivec
Messages : 91
Inscription : sam. 18/sept./2010 18:13

Re: SOS Flou gausian

Message par Demivec »

@manababel: Sur les processeurs x64, les registres volatils disponibles sont: rax, rcx, rdx, r8, r9, xmm0, xmm1, xmm2 et xmm3. Tous les autres doivent toujours être préservés.

Dans votre code, les registres rbx et rsi ne sont pas conservés. Il existe également d'autres registres qui devraient être conservés. Vous rencontrerez des problèmes lorsque vous «pousserez» et «pop» les registres si vous modifiez également le registre de pile rsi.
manababel
Messages : 144
Inscription : jeu. 14/mai/2020 7:40

Re: SOS Flou gausian

Message par manababel »

Merci pour vos renseignements Demivic
Apparemment, pour utiliser la "pile" , je dois réserver une zone mémoire puis "pointer" la "pile" dessus.



Code : Tout sélectionner

;EnableExplicit
;-------------------------------------------------------------------------------
UseJPEGImageDecoder()
UsePNGImageDecoder()

;-- http://blog.ivank.net/fastest-gaussian-blur.html
;Procedure boxesForGauss(sigma, n)  ; standard deviation, number of boxes
    ;wIdeal = Math.sqrt((12*sigma*sigma/n)+1);  // Ideal averaging filter width 
    ;wl = floor(wIdeal)
    ;If(wl%2==0) wl--
    ;wu = wl+2	
    ;mIdeal = (12*sigma*sigma - n*wl*wl - 4*n*wl - 3*n)/(-4*wl - 4)
    ;m = Math.round(mIdeal)
    ;var sizes = []
    ;For(var i=0 To 2
      ;(i<m?wl:wu);
    ;Next
    ;Return sizes
;EndProcedure
    
Procedure boxBlurH_4(source, cible, lg, ht, opt)
  Protected r,g,b , r1,g1,b1 , r2,g2,b2 , d.f,d2.f , var ,y,x , pos
  Protected np , var1,var2,var3 , s
  
  Dim save.q(20) ; 20*64bits = 10*128bits (5 registres 128bits + 5 registres 64bits)
  Dim d2.f(opt)
  Dim pix.l(4)
  np=@pix()
  s=@save()
  
  For i=0 To opt
    d2(i)=1/(i+opt)
  Next
  d.f=1/(opt+opt+1)
  
  For y=0 To ht-1
    pos=source+(lg*y*4)
    
    ; flou sur la partie gauche de l'image ( de 0 a opt )
    r=0:g=0:b=0
    For x=0 To (opt*2)
      var=PeekL(pos+x*4)
      b1=Red(var) : g1=Green(var) : r1=Blue(var)
      r=r+r1 : g=g+g1 : b=b+b1
    Next
    r2=r:g2=g:b2=b
    
    For x=opt To 0 Step -1
      var=PeekL(pos+(x+opt)*4)
      b1=Red(var) : g1=Green(var) : r1=Blue(var)
      r=r-r1 : g=g-g1 : b=b-b1
      r1=r*d2(x) : g1=g*d2(x) : b1=b*d2(x)
      PokeL(cible+(lg*y+x)*4,(r1<<16)+(g1<<8)+b1)
    Next
    
    ; flou sur la partie central de l'image ( de opt a lg-opt )
    pos=source+(lg*y*4)
    pix(0)=b2:pix(1)=g2:pix(2)=r2
    x=opt+1
    var1=(pos+(x-opt-1)*4)
    var2=(pos+(x+opt)*4)
    var3=(cible+(lg*y+x)*4)
    EnableASM
    
    ; partie a modifier pour utiliser la "pile" 
    ; push/pop ne fonctionnent pas avec les registre mmx
    ;ASSUME SS:segment_pile
    ;MOV  AX, segment_pile
    ;MOV  SS, AX		; initialise le segment de pile
    ;MOV  SP, base_pile ; copie l'adresse de la base de la pile dans SP
    
    !mov rax,[p.v_s]
    !movdqu [rax],xmm0
    !movdqu [rax+16],xmm1
    !movdqu [rax+32],xmm2
    !movdqu [rax+48],xmm3
    !movdqu [rax+64],xmm15
    !mov [rax+80],r8
    !mov [rax+88],r9
    !mov [rax+96],r12
    !mov [rax+112],rdx
    !mov [rax+120],rcx
    
    !mov r8,[p.v_var1]
    !mov r9,[p.v_var2]
    !mov r12,[p.v_var3]
    !pxor xmm15,xmm15
    !VPBROADCASTD xmm3,[p.v_d]
    !mov rax,[p.v_np]
    !movdqu xmm2,[rax]
    !mov rcx,[p.v_opt] ;For x=opt+1 
    !inc rcx
    !mov rdx,[p.v_lg] ;To lg-opt-1
    !sub rdx,[p.v_opt]
    !dec rdx
    
    !boxBlurH_saut1:
      !movd xmm0,[r8]  ;var=PeekL(pos+(x-opt-1)*4)
      !punpcklbw xmm0,xmm15 ;RGBReturn(var,r1,g1,b1)
      !punpcklwd xmm0,xmm15
      !movd xmm1,[r9]  ;var=PeekL(pos+(x+opt)*4)
      !punpcklbw xmm1,xmm15 ;RGBReturn(var,r2,g2,b2)
      !punpcklwd xmm1,xmm15
      !psubd xmm2,xmm0 ; r=r-r1
      !paddd xmm2,xmm1 ; r=r+r2
      !movdqu xmm0,xmm2
      !cvtdq2ps xmm0,xmm0
      !mulps xmm0,xmm3 ;r1=r*d  : d = 1/(opt+opt+1)
      !cvtps2dq xmm0,xmm0
      !packusdw xmm0,xmm15
      !packuswb xmm0,xmm15
      !movd [r12],xmm0 ;PokeL(cible+(lg*y+x)*4,(r1<<16)+(g1<<8)+b1)
      !add r8,4
      !add r9,4
      !add r12,4
      !inc rcx
      !cmp rcx,rdx
    !jbe boxBlurH_saut1
    
    !mov rax,[p.v_s]
    !movdqu xmm0,[rax]
    !movdqu xmm1,[rax+16]
    !movdqu xmm2,[rax+32]
    !movdqu xmm3,[rax+48]
    !movdqu xmm15,[rax+64]
    !mov r8,[rax+80]
    !mov r9,[rax+88]
    !mov r12,[rax+96]
    !mov rdx,[rax+112]
    !mov rcx,[rax+120]
    DisableASM  
    
    ;flou sur la partie droite de l'image ( de lg-opt a lg )
    r=0:g=0:b=0
    For x=lg-(opt*2) To lg-1
      var=PeekL(pos+x*4)
      b1=Red(var) : g1=Green(var) : r1=Blue(var)  
      r=r+r1 : g=g+g1 : b=b+b1
    Next
    
    compt=opt-1
    For x=lg-opt To lg-1
      var=PeekL(pos+(x-opt)*4)
      b1=Red(var) : g1=Green(var) : r1=Blue(var)
      r=r-r1 : g=g-g1 : b=b-b1
      r1=r*d2(lg-x-1) : g1=g*d2(lg-x-1) : b1=b*d2(lg-x-1)
      PokeL(cible+(lg*y+x)*4,(r1<<16)+(g1<<8)+b1)
      compt=compt-1
    Next
  Next
  FreeArray(pix())
  FreeArray(d2())
  FreeArray(save())
EndProcedure

Procedure boxBlurT_4(source, cible, lg, ht, opt)
  
  Protected r,g,b , r1,g1,b1 , r2,g2,b2 , d.f,d2.f , var ,y,x , pos
  Protected np , var1,var2,var3 , var4 , s
  
  Dim save.q(20) 
  Dim d2.f(opt)
  Dim pix.l(4)
  np=@pix()
  s=@save()
  For i=0 To opt
    d2(i)=1/(i+opt)
  Next
  d.f=1/(opt+opt+1)
  For x=0 To lg-1
    
    r=0:g=0:b=0
    For y=0 To (opt*2)
      var=PeekL(source+(y*lg+x)*4)
      b1=Red(var) : g1=Green(var) : r1=Blue(var)  
      r=r+r1 : g=g+g1 : b=b+b1
    Next
    r2=r:g2=g:b2=b
    For y=opt To 0 Step -1
      var=PeekL(source+(y*lg+x)*4)
      b1=Red(var) : g1=Green(var) : r1=Blue(var)
      r=r-r1 : g=g-g1 : b=b-b1
      r1=r*d2(y) : g1=g*d2(y) : b1=b*d2(y)
      PokeL(cible+(lg*y+x)*4,(r1<<16)+(g1<<8)+b1)
    Next
    
    pix(0)=b2:pix(1)=g2:pix(2)=r2
    y=opt+1
    var1=(source+((y-opt-1)*lg+x)*4)
    var2=(source+((y+opt)*lg+x)*4)
    var3=(cible+(lg*y+x)*4)
    var4=lg*4
    EnableASM
    !mov rax,[p.v_s]
    !movdqu [rax],xmm0
    !movdqu [rax+16],xmm1
    !movdqu [rax+32],xmm2
    !movdqu [rax+48],xmm3
    !movdqu [rax+64],xmm15
    !mov [rax+80],r8
    !mov [rax+88],r9
    !mov [rax+96],r12
    !mov [rax+104],r13
    !mov [rax+112],rdx
    !mov [rax+120],rcx
    
    !mov r8,[p.v_var1]
    !mov r9,[p.v_var2]
    !mov r12,[p.v_var3]
    !mov r13,[p.v_var4]
    !pxor xmm15,xmm15
    !VPBROADCASTD xmm2,[p.v_d]
    !mov rax,[p.v_np]
    !movdqu xmm3,[rax]
    !mov rcx,[p.v_opt] ;For y=opt+1 
    !inc rcx
    !mov rdx,[p.v_ht] ;to ht-opt-1
    !sub rdx,[p.v_opt]
    !dec rdx
    
    !boxBlurT_saut1:
      !movd xmm0,[r8]  ;var=PeekL(pos+(x-opt-1)*4)
      !punpcklbw xmm0,xmm15 ;RGBReturn(var,r1,g1,b1)
      !punpcklwd xmm0,xmm15
      !movd xmm1,[r9]  ;var=PeekL(pos+(x+opt)*4)
      !punpcklbw xmm1,xmm15 ;RGBReturn(var,r2,g2,b2)
      !punpcklwd xmm1,xmm15
      !psubd xmm3,xmm0 ; r=r-r1
      !paddd xmm3,xmm1 ; r=r+r2
      !movdqu xmm0,xmm3
      !cvtdq2ps xmm0,xmm0
      !mulps xmm0,xmm2 ;r1=r*d  : d = 1/(opt+opt+1)
      !cvtps2dq xmm0,xmm0
      !packusdw xmm0,xmm15
      !packuswb xmm0,xmm15
      !movd [r12],xmm0 ;PokeL(cible+(lg*y+x)*4,(r1<<16)+(g1<<8)+b1)
      !add r8,r13
      !add r9,r13
      !add r12,r13
      !inc rcx
      !cmp rcx,rdx
    !jbe boxBlurT_saut1
    
    !mov rax,[p.v_s]
    !movdqu xmm0,[rax]
    !movdqu xmm1,[rax+16]
    !movdqu xmm2,[rax+32]
    !movdqu xmm3,[rax+48]
    !movdqu xmm15,[rax+64]
    !mov r8,[rax+80]
    !mov r9,[rax+88]
    !mov r12,[rax+96]
    !mov r13,[rax+104]
    !mov rdx,[rax+112]
    !mov rcx,[rax+120]
    
    DisableASM  
    
    r=0:g=0:b=0
    For y=ht-(opt*2) To ht-1
      var=PeekL(source+(lg*y+x)*4)
      b1=Red(var):g1=Green(var):r1=Blue(var)  
      r=r+r1 : g=g+g1 :b=b+b1
    Next

    For y=ht-opt To ht-1
      var=PeekL(source+((y-opt)*lg+x)*4)
      b1=Red(var) : g1=Green(var) : r1=Blue(var)
      r=r-r1 : g=g-g1 : b=b-b1
      r1=r*d2(ht-y-1) : g1=g*d2(ht-y-1) : b1=b*d2(ht-y-1)
      PokeL(cible+(lg*y+x)*4,(r1<<16)+(g1<<8)+b1)
    Next
  Next
  FreeArray(pix())
  FreeArray(d2()) 
  FreeArray(save())
  EndProcedure
  
Procedure boxBlur_4 (source, cible, lg, ht, r)
  CopyMemory(source, cible, lg*ht*4)
  boxblurT_4(cible,source,lg,ht,r) ; passe horizontal
  boxBlurH_4(source,cible,lg,ht,r) ; passe vertical
EndProcedure

Procedure Filter_GaussBlur(source,cible,r)
  Protected lg,ht,bit,source2,taille
  ht = ImageHeight(source)
  lg = ImageWidth(source)
  
  If lg>ht
    If r>=(ht/2):r=(ht/2)-1:EndIf
  Else
    If r>=(lg/2):r=(lg/2)-1:EndIf
  EndIf
  If r<1:r=1:EndIf
 
  StartDrawing(ImageOutput(source))
  source=DrawingBuffer()
  bit=OutputDepth()
  StopDrawing()

  StartDrawing(ImageOutput(cible))
  cible=DrawingBuffer()
  StopDrawing()
  
  taille=lg*ht*4
  source2=AllocateMemory(taille)
  If bit=32
    CopyMemory(source, source2, taille)
  Else
    Dim save.q(4)
    s=@save()
    EnableASM
      !mov rax,[p.v_s]
      !mov [rax],rcx
      !mov [rax+8],rdx
      !mov [rax+16],r8

      !mov rcx,[p.v_source]
      !mov rdx,[p.v_source2]
      !mov r8,[p.v_taille]
      !shr r8,2
      !copy_boucle24:
        !mov eax,[rcx]     
        !mov [rdx],eax
        !add rcx,3
        !add rdx,4
        !dec r8
       !jnz copy_boucle24
 
      !mov rax,[p.v_s] 
      !mov rcx,[rax]
      !mov rdx, [rax+8]
      !mov r8,[rax+16]
    DisableASM
    FreeArray(save())
  EndIf
  
  ;r()=boxesForGauss(sigma, n) ; partie a ajouter pour avoir un meilleur rendu
  boxBlur_4(source2, cible, lg, ht, r) ; passe 1
  boxBlur_4(cible, source2, lg, ht, r) ; passe 2
  boxBlur_4(source2, cible, lg, ht, r) ; passe 3
  
  FreeMemory(source2)
  EndProcedure
  

Global imgx=1200
Global imgy=800

If OpenWindow(0, 0, 0, imgx+50, imgy+50, "PixLab", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

   pic$ = OpenFileRequester("Image indexe",pic$,"",0)
   source=10
   cible=20
   If pic$ <> ""
     If LoadImage(source,pic$)
       ResizeImage(source,imgx,imgy,#PB_Image_Smooth)
     Else
       End
     EndIf
   Else
     End
   EndIf
   
   CreateImage(cible,imgx,imgy,32)
  
   t.q=ElapsedMilliseconds()
     Filter_GaussBlur(source,cible,5)
   t1.q=ElapsedMilliseconds()-t

   StartDrawing(WindowOutput(0))
   DrawImage(ImageID(cible),0,0)
   DrawText(5,5,Str(t1))

   StopDrawing()
   
   Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
 EndIf
 
 ;-------------------------------------------------------------------------------
Répondre