effet riple

Programmation d'applications complexes
manababel
Messages : 144
Inscription : jeu. 14/mai/2020 7:40

effet riple

Message par manababel »

Code : Tout sélectionner

;***********************************************
;Titre      : Water Ripples
 
;Date       : 03/07/2021
;Version PB : PureBasic 5.70 LTS (Windows - x64)
;
;Info       : ne fonctionne qu'avec des images 32bits
;             la fonction "load_image" convertis les images 24bits en 32bits            
;***********************************************

EnableExplicit

UseJPEGImageDecoder()
UseJPEG2000ImageDecoder()
UsePNGImageDecoder()
UseTGAImageDecoder()
UseTIFFImageDecoder()
UseGIFImageDecoder()
; 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
;------------------------------------------------------------------


Procedure main( source , cible , radius.f , amp.f , wavelength.f  , t=0)
  Protected lg ,ht , taille
  Protected source_p , cible_p
  Protected x , y, dx , dy , dis , var , am.f , xx , yy , pos , pos2
  
  StartDrawing(ImageOutput(source))
  lg = ImageWidth(source)
  ht = ImageHeight(source)
  taille=lg*ht*4
  source_p=DrawingBuffer()
  StopDrawing()
  
  StartDrawing(ImageOutput(cible))
  lg = ImageWidth(cible)
  ht = ImageHeight(cible)
  taille=lg*ht*4
  cible_p=DrawingBuffer()
  StopDrawing()
  
  For y=0 To ht-1
    For x=0 To lg-1
      dx = x - lg/2
      dy = y - ht/2
      dis = Sqr(dx*dx+dy*dy)
      pos = (y*lg+x)*4
      If dis>radius
        var = PeekL(source_p + pos)
        PokeL(cible_p + pos , var)
      Else
        am = amp * Sin((dis / wavelength )+Radian(t/6.28))
        am = am * (radius-dis)/radius         
        If dis<>0
          am = am * wavelength / dis
          xx = x + dx * am
          yy = y + dy * am
          If xx<0 : xx=0 : EndIf
          If yy<0 : yy=0 : EndIf
          If xx>lg-1 : xx=lg-1 : EndIf
          If yy>ht-1 : yy=ht-1 : EndIf
          pos2 = (yy*lg+xx)*4
          var = PeekL(source_p + pos2)
          PokeL(cible_p + pos , var)
        EndIf
      EndIf
    Next
  Next             
        
EndProcedure




Global imgx=800
Global imgy=600
          
If OpenWindow(0, 0, 0, imgx, imgy+60, "Water Ripples...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
   Define source , cible , t , t1 , t2 ,ti , file$
  
  ; Détermine le rayon où sera l'affect
  TrackBarGadget(1, 0, 0, imgx, 19, 1, imgx )
  ; selectionne "le nombre de vagues" 
  TrackBarGadget(2, 0, 20, imgx, 19, 1, imgx )
  ; selectionne "la force de la vague" 
  TrackBarGadget(3, 0, 40, imgx, 19, 1, imgx )
  
  source = 4
  cible = 5
  
  file$ = OpenFileRequester("Image","","",0)
  If Not Load_Image(source,file$) ; <- commande differente de "LOADIMAGE"
    MessageRequester("load_image","erreur de chargement",#PB_MessageRequester_Ok | #PB_MessageRequester_Error)
    End
  EndIf
  ResizeImage(source,imgx,imgy,#PB_Image_Smooth)
  
  CreateImage(cible,imgx,imgy,32)
  
  t2=ElapsedMilliseconds()+100
  Repeat 
   
   t=ElapsedMilliseconds()
   main(source,cible,GetGadgetState(1),GetGadgetState(2)/50,GetGadgetState(3)/10,ti)
   t1=ElapsedMilliseconds()-t

   StartDrawing(WindowOutput(0))
   DrawImage(ImageID(cible),0,60)
   ;DrawText(5,5,Str(t1))
   StopDrawing()
   
   If ElapsedMilliseconds()>t2
     t2=ElapsedMilliseconds()+100
     ti=t+1
     If t>360 : t=0 : EndIf
   EndIf
   
   Delay(1)
   Until WindowEvent() = #PB_Event_CloseWindow
 EndIf
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: effet riple

Message par blendman »

Magnifique !

J'ai modifié un peu le code pour essayer de faire un effet de déformation en fonction de la position de la souris (smudge).
ce n'est pas encore tout à fait ça, mais c'est déjà super sympa ^^.

Tu penses qu'il y aurait moyen de l'adapter pour avoir cet effet (smudge) sur une image ? Comme l'outil "doigt" dans photoshop ?
Déplacer des pixels à la main ?

Car là, on peut le faire, et c'est vraiment sympa, mais avec un coté "bord un peu flouté", ou en utilisant une image comme "brush" (au lieu d'un cercle), ce sera génial :).

Mon code modifié :

Code : Tout sélectionner

;***********************************************
;Titre      : Water Ripples

;Date       : 03/07/2021
;Version PB : PureBasic 5.70 LTS (Windows - x64)
;
;Info       : ne fonctionne qu'avec des images 32bits
;             la fonction "load_image" convertis les images 24bits en 32bits            
;***********************************************

EnableExplicit

UseJPEGImageDecoder()
UseJPEG2000ImageDecoder()
UsePNGImageDecoder()
UseTGAImageDecoder()
UseTIFFImageDecoder()
UseGIFImageDecoder()

Global mx, my

; 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
;------------------------------------------------------------------


Procedure main( source , cible , radius.f , amp.f , wavelength.f  , t=0)
  Protected lg ,ht , taille
  Protected source_p , cible_p
  Protected x , y, dx , dy , dis , var , am.f , xx , yy , pos , pos2, img
  
  StartDrawing(ImageOutput(source))
  lg = ImageWidth(source)
  ht = ImageHeight(source)
  taille=lg*ht*4
  source_p=DrawingBuffer()
  StopDrawing()
  
  img = cible
  img = source
  StartDrawing(ImageOutput(img))
  lg = ImageWidth(img)
  ht = ImageHeight(img)
  taille=lg*ht*4
  cible_p=DrawingBuffer()
  StopDrawing()
  
  For y=0 To ht-1
    For x=0 To lg-1
      dx = x - mx ; x- lg/2
      dy = y + my - ht -radius/2 ;y- ht/2
      dis = Sqr(dx*dx+dy*dy)
      pos = (y*lg+x)*4
      If dis>radius
        var = PeekL(source_p + pos)
        PokeL(cible_p + pos , var)
      Else
        am = amp * Sin((dis / wavelength )+Radian(t/6.28))
        am = am * (radius-dis)/radius         
        If dis<>0
          am = am * wavelength / dis
          xx = x + dx * am
          yy = y + dy * am
          If xx<0 : xx=0 : EndIf
          If yy<0 : yy=0 : EndIf
          If xx>lg-1 : xx=lg-1 : EndIf
          If yy>ht-1 : yy=ht-1 : EndIf
          pos2 = (yy*lg+xx)*4
          var = PeekL(source_p + pos2)
          PokeL(cible_p + pos , var)
        EndIf
      EndIf
    Next
  Next             
  
EndProcedure




Global imgx=800
Global imgy=600
Define mousedown = 0, event=0

If OpenWindow(0, 0, 0, imgx, imgy+60, "Water Ripples...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  Define source , cible , t , t1 , t2 ,ti , file$
  
  ; Détermine le rayon où sera l'affect
  TrackBarGadget(1, 0, 0, imgx, 19, 1, imgx )
  ; selectionne "le nombre de vagues" 
  TrackBarGadget(2, 0, 20, imgx, 19, 1, imgx )
  ; selectionne "la force de la vague" 
  TrackBarGadget(3, 0, 40, imgx, 19, 1, imgx )
  
  source = 4
  cible = 5
  
  file$ = OpenFileRequester("Image","","",0)
  If Not Load_Image(source,file$) ; <- commande differente de "LOADIMAGE"
    MessageRequester("load_image","erreur de chargement",#PB_MessageRequester_Ok | #PB_MessageRequester_Error)
    End
  EndIf
  ResizeImage(source,imgx,imgy,#PB_Image_Smooth)
  
  CreateImage(cible,imgx,imgy,32)
  
  t2=ElapsedMilliseconds()+100
  StartDrawing(WindowOutput(0))
  ; DrawImage(ImageID(cible),0,60)
  DrawImage(ImageID(source),0,60)
  ;DrawText(5,5,Str(t1))
  StopDrawing()
  
  Repeat 
    
    mx = WindowMouseX(0)
    my = WindowMouseY(0)
    event = WaitWindowEvent(1)
    
    If event = #WM_LBUTTONDOWN
      mousedown =1
    ElseIf event = #PB_Event_LeftClick
      mousedown = 0
    EndIf
    
    
    If mousedown
      t=ElapsedMilliseconds()
      main(source,cible,GetGadgetState(1),GetGadgetState(2)/50,GetGadgetState(3)/10,ti)
      t1=ElapsedMilliseconds()-t
      
      
      StartDrawing(WindowOutput(0))
      ; DrawImage(ImageID(cible),0,60)
      DrawImage(ImageID(source),0,60)
      ;DrawText(5,5,Str(t1))
      StopDrawing()
    EndIf 
    
    If ElapsedMilliseconds()>t2
      t2=ElapsedMilliseconds()+100
      ti=t+1
      If t>360 : t=0 : EndIf
    EndIf
    
    Delay(1)
  Until event = #PB_Event_CloseWindow
EndIf

Le résultat :
Image

Un immense merci en tout cas c'est vraiment chouette ;)
Avatar de l’utilisateur
kernadec
Messages : 1606
Inscription : ven. 25/avr./2008 11:14

Re: effet riple

Message par kernadec »

bjr manababel
merci pour le partage
Excellent j'ai pu refaire le graphisme des tee shorts Hippies du marché aux puces
que je portait à l"époque du festival de Woodstock en 1969 :mrgreen:
Cordialement
manababel
Messages : 144
Inscription : jeu. 14/mai/2020 7:40

Re: effet riple

Message par manababel »

je ne suis pas sur de savoir ce que c'est l'effet "smudge"
voici ce que j'ai cru comprendre.( un effet tache flou ? )

Code : Tout sélectionner

;***********************************************
;Titre      : Water Ripples

;Date       : 03/07/2021
;Version PB : PureBasic 5.70 LTS (Windows - x64)
;
;Info       : ne fonctionne qu'avec des images 32bits
;             la fonction "load_image" convertis les images 24bits en 32bits            
;***********************************************

EnableExplicit

UseJPEGImageDecoder()
UseJPEG2000ImageDecoder()
UsePNGImageDecoder()
UseTGAImageDecoder()
UseTIFFImageDecoder()
UseGIFImageDecoder()

Global mx, my

; 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
;------------------------------------------------------------------


Procedure main( source , cible , radius.f , amp.f , wavelength.f  , t=0)
  Protected lg ,ht , taille
  Protected source_p , cible_p
  Protected x , y, dx , dy , dis , var , am.f , xx , yy , pos , pos2, pos3 , img
  Protected rgb , r , g , b , x1 , y1 , nxx , nyy
  
  StartDrawing(ImageOutput(source))
  lg = ImageWidth(source)
  ht = ImageHeight(source)
  taille=lg*ht*4
  source_p=DrawingBuffer()
  StopDrawing()
  
  img = cible
  img = source
  StartDrawing(ImageOutput(img))
  lg = ImageWidth(img)
  ht = ImageHeight(img)
  taille=lg*ht*4
  cible_p=DrawingBuffer()
  StopDrawing()
  
  For y=0 To ht-1
    For x=0 To lg-1
      dx = x - mx ; x- lg/2
      dy = y + my - ht -radius/2 ;y- ht/2
      dis = Sqr(dx*dx+dy*dy)
      pos = (y*lg+x)*4
      If dis>radius
        var = PeekL(source_p + pos)
        PokeL(cible_p + pos , var)
      Else
        am = amp * Sin((dis / wavelength )+Radian(t/6.28))
        am = am * (radius-dis)/radius         
        If dis<>0
          am = am * wavelength / dis
          xx = x + dx * am
          yy = y + dy * am
          r=0:g=0:b=0
          For y1=-1 To 1
            For x1=-1 To 1
              nxx=xx+x1
              nyy=yy+1
              If nxx<0 : nxx=0 : EndIf
              If nyy<0 : nyy=0 : EndIf
              If nxx>lg-1 : nxx=lg-1 : EndIf
              If nyy>ht-1 : nyy=ht-1 : EndIf
              pos3 = (nyy*lg+nxx)*4
              rgb=PeekL(source_p + pos3)
              r=r+((rgb>> 16)& 255)
              g=g+((rgb>> 8)& 255)
              b=b+(rgb & 255)
            Next
          Next
          r=r/9
          g=g/9
          b=b/9
          pos2 = (yy*lg+xx)*4
          PokeL(cible_p + pos , r<<16 + g<<8 + b)
        EndIf
      EndIf
    Next
  Next             
  
EndProcedure




Global imgx=800
Global imgy=600
Define mousedown = 0, event=0

If OpenWindow(0, 0, 0, imgx, imgy+60, "Water Ripples...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  Define source , cible , t , t1 , t2 ,ti , file$
  
  ; Détermine le rayon où sera l'affect
  TrackBarGadget(1, 0, 0, imgx, 19, 1, imgx )
  ; selectionne "le nombre de vagues" 
  TrackBarGadget(2, 0, 20, imgx, 19, 1, imgx )
  ; selectionne "la force de la vague" 
  TrackBarGadget(3, 0, 40, imgx, 19, 1, imgx )
  
  source = 4
  cible = 5
  
  file$ = OpenFileRequester("Image","","",0)
  If Not Load_Image(source,file$) ; <- commande differente de "LOADIMAGE"
    MessageRequester("load_image","erreur de chargement",#PB_MessageRequester_Ok | #PB_MessageRequester_Error)
    End
  EndIf
  ResizeImage(source,imgx,imgy,#PB_Image_Smooth)
  
  CreateImage(cible,imgx,imgy,32)
  
  t2=ElapsedMilliseconds()+100
  StartDrawing(WindowOutput(0))
  ; DrawImage(ImageID(cible),0,60)
  DrawImage(ImageID(source),0,60)
  ;DrawText(5,5,Str(t1))
  StopDrawing()
  
  Repeat 
    
    mx = WindowMouseX(0)
    my = WindowMouseY(0)
    event = WaitWindowEvent(1)
    
    If event = #WM_LBUTTONDOWN
      mousedown =1
    ElseIf event = #PB_Event_LeftClick
      mousedown = 0
    EndIf
    
    
    If mousedown
      t=ElapsedMilliseconds()
      main(source,cible,GetGadgetState(1),GetGadgetState(2)/50,GetGadgetState(3)/10,ti)
      t1=ElapsedMilliseconds()-t
      
      
      StartDrawing(WindowOutput(0))
      ; DrawImage(ImageID(cible),0,60)
      DrawImage(ImageID(source),0,60)
      ;DrawText(5,5,Str(t1))
      StopDrawing()
    EndIf 
    
    If ElapsedMilliseconds()>t2
      t2=ElapsedMilliseconds()+100
      ti=t+1
      If t>360 : t=0 : EndIf
    EndIf
    
    Delay(1)
  Until event = #PB_Event_CloseWindow
EndIf
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: effet riple

Message par blendman »

coucou

Ton nouveau code est super intéressant, on peut s'en servir pour donner un effet de peinture qui fait des trainées vers le bas, c'est plutôt sympa.

Le "smudge", c'est déplacer les pixels avec le mouvement de la souris. Donc si ta souris (cliquée) va sur la droite, elle déplace les pixels (comme ce que tu viens de faire, un déplacement flou), mais en suivant la direction de la souris.

là, j'ai fait un smudge dans gimp :
Image

Les "trainés floues" qu'on voit, c'est parce que je clique puis je déplace la souris, et les pixels suivent le mouvement de ma souris. c'est ce genre d'outil dont je parlais ;).



Par contre, avec ton code au-dessus, on ne pourrait par faire un simple "flou" sur les pixels là où se trouve la souris (sans que ça descende vers le bas) ?
Ce serait super génial aussi ;).

Merci encore.
Avatar de l’utilisateur
Kwai chang caine
Messages : 6989
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: effet riple

Message par Kwai chang caine »

Splendide effet !!! 8O
Un peu puissant pour mon PC qui met une plombe pour les faires
Mais aprés quelques secondes d'attente interminables, je chantais devant mon écran
Je ne veux pas l'aumône,
Je ne veux pas déranger,
Mais juste un peu d'eau,
Faire des ricocheeeeeeets !!!! :D

Merci beaucoup de ce joli partage 8)
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Répondre