filtre brightness - bend

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

filtre brightness - bend

Message par manababel »

voici deux filtres qui permettent de jouer sur la luminosité d'une image

le filtre "brightness"
- new pixel = pixel + Val ( Val peut être négatif ou positif )

le filtre "bend"
- new pixel = sin (pixel * val) * 127 + val
( la valeur 'val' doit être comprise entre 0 et 360 )
- toutes les nouvelles valeurs sont précalculées et stockées dans un tableau.
D'autres filtre fonctionnent de la même façon, comme le filtre "gamma"

Code : Tout sélectionner

EnableExplicit

Global Dim Reg_memory.q(4*344)

; charge une image et la convertie en 32bit
;-------------------------------------------------------------------
Procedure load_image(nom,file$)
  Protected source_p , cible_p , s.q
  Protected lg.q , ht.q , taille.q , depth.q
 
  LoadImage(nom,file$)
  If Not IsImage(nom) : ProcedureReturn 0 : EndIf
   
  StartDrawing(ImageOutput(nom))
  source_p = DrawingBuffer()
  ht = ImageHeight(nom)
  lg = ImageWidth(nom)
  Depth=OutputDepth()
  StopDrawing()

  If Depth=24
    taille=lg*ht
    cible_p=AllocateMemory(taille*4)
    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_p]
      !mov rdx,[p.v_cible_p]
      !mov r8,[p.v_taille]
      !sub r8,1 ; <---------------- ????
      !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())
   
    FreeImage(nom) ; supprime l'image 24bits
    CreateImage(nom,lg,ht,32)
    StartDrawing(ImageOutput(nom))
    source_p = DrawingBuffer()
    StopDrawing()
    CopyMemory( cible_p , source_p , taille*4 )
    FreeMemory(cible_p)
  EndIf
  
  ProcedureReturn 1
EndProcedure




; partie du programme à modifier pour adapter se programme au votre
; convertie les "IDs" des images en pointer d'adresse
; test si les images sont en 32bits et de la meme taille
;-------------------------------------------------------------------

Macro sp(source,cible)
  Protected Depth.q , lg.q , ht.q , lg1.q , ht1.q , taille.q
  Protected cible_p.q , source_p.q
 
  StartDrawing(ImageOutput(cible))
  cible_p = DrawingBuffer()
  ht1 = ImageHeight(cible)
  lg1 = ImageWidth(cible)
  Depth=OutputDepth()
  StopDrawing()
  If depth<>32 : ProcedureReturn : EndIf
 
  StartDrawing(ImageOutput(source))
  source_p = DrawingBuffer()
  ht = ImageHeight(source)
  lg = ImageWidth(source)
  Depth=OutputDepth()
  StopDrawing()
  If depth<>32 : ProcedureReturn : EndIf
 
  If lg<>lg1 Or ht<>ht1 : ProcedureReturn : EndIf
 
  taille = lg * ht
EndMacro

Macro clampRGB(r,g,b)
  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
EndMacro

Macro returnRGB(pixel,r,g,b)
    r=(pixel & $ff0000)>>16
    g=(pixel & $ff00)>>8
    b=(pixel & $ff)
  EndMacro
 
;-------------------------------------------------------------------
; sauvegarde de registres
Macro Save_reg()
  s=@reg_memory()
  EnableASM
  !mov rax,[p.v_s]
  !mov [rax+000],rbx
  !mov [rax+008],rcx ;
  !mov [rax+016],rdx ;
  !mov [rax+024],rsi
  !mov [rax+032],rdi
  !mov [rax+040],r8 ;
  !mov [rax+048],r9 ;
  !mov [rax+056],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
  DisableASM
EndMacro

Macro Rest_Reg()
; restore les registres
  s=@reg_memory()
  EnableASM
  !mov rax,[p.v_s]
  !mov rbx,[rax+000]
  !mov rcx,[rax+008]
  !mov rdx,[rax+016]
  !mov rsi,[rax+024]
  !mov rdi,[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]
  DisableASM

EndMacro
;-------------------------------------------------------------------

Procedure Filter_bend_pb(source.q,cible.q,r.q,g.q,b.q)
  Protected i.q , pixel.l , v.f
  Protected r1.f , g1.f , b1.f
 
  sp(source,cible)
 
  ;If r<0:r=0:EndIf
  ;If g<0:g=0:EndIf
  ;If b<0:b=0:EndIf
  ;If r>360:r=360:EndIf
  ;If g>360:g=360:EndIf
  ;If b>360:b=360:EndIf
 
  r=r-180
  g=g-180
  b=b-180
 
  r1.f=r/255.0*3.14/180.0
  g1.f=g/255.0*3.14/180.0
  b1.f=b/255.0*3.14/180.0
 
  Dim tabr(255)
  Dim tabg(255)
  Dim tabb(255)
 
  For i=0 To 255
    tabr(i)=Sin(i*r1)*127+i
    tabg(i)=Sin(i*g1)*127+i
    tabb(i)=Sin(i*b1)*127+i
    clampRGB(tabr(i),tabg(i),tabb(i))
  Next
 
  For i=0 To taille
    pixel=PeekL(source_p+i*4)
    returnRGB(pixel,r,g,b)
    PokeL(cible_p+i*4, tabr(r)<<16 + tabg(g)<<8 + tabb(b))
  Next
  FreeArray(tabr())
  FreeArray(tabg())
  FreeArray(tabb())
 
EndProcedure


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

; min = 0  :  max = 360
Procedure Filter_bend(source.q,cible.q,r.q,g.q,b.q)
  Protected s.q , palr.q , palg.q , palb.q , v.f , i.q
  Protected r1.f , g1.f , b1.f
 
  sp(source,cible)
 
  r=r-180
  g=g-180
  b=b-180
 
  r1.f=r/255.0*3.14/180.0
  g1.f=g/255.0*3.14/180.0
  b1.f=b/255.0*3.14/180.0
 
  Dim tabr(255)
  Dim tabg(255)
  Dim tabb(255)
  palr=@tabr()
  palg=@tabg()
  palb=@tabb()
  For i=0 To 255
    tabr(i)=Sin(i*r1)*127+i
    tabg(i)=Sin(i*g1)*127+i
    tabb(i)=Sin(i*b1)*127+i
    clampRGB(tabr(i),tabg(i),tabb(i))
  Next
 
  Dim save.q(14)
  s=@save()
 
  EnableASM
  Save_reg()
  !mov rsi,[p.v_source_p]
  !mov rdi,[p.v_cible_p]
  !mov r8,[p.v_palr]
  !mov r9,[p.v_palg]
  !mov r10,[p.v_palb]
  !mov rdx,[p.v_taille]
  !bend_2:
    !xor rax,rax
    !xor rbx,rbx
    !mov bl,[rsi+2]
    !mov al,[r8+rbx*8]
    !shl rax,8
    !mov bl,[rsi+1]
    !mov al,[r9+rbx*8]
    !shl rax,8
    !mov bl,[rsi+0]
    !mov al,[r10+rbx*8]
    !mov [rdi],eax
    !add rsi,4
    !add rdi,4 
    !sub rdx,1
  !jnz bend_2 
  Rest_reg()
  DisableASM
  FreeArray(save())
  FreeArray(tabr())
  FreeArray(tabg())
  FreeArray(tabb())
EndProcedure
;-------------------------------------------------------------------

Procedure Filter_Brightness(source,cible,r,g,b)
  Protected color.q , s.q
  sp(source,cible)
  color = r<<32 + g<<16 + b
  EnableASM
  Save_reg()
  !pxor xmm3,xmm3
    !mov rsi,[p.v_source_p]
    !mov rdi,[p.v_cible_p]
    !mov rdx,[p.v_taille]
    !shr rdx,1
    !mov rax,[p.v_color]
    !movq xmm0,rax
    !VPBROADCASTQ xmm0,xmm0 ; | 64bits A | 64 bits B |   ; A = B
    !xor rcx,rcx
    !Filter_Brightness_1:
    !movq xmm1,[rsi+rcx]
      !punpcklbw xmm1,xmm3 ; converti r,g,b 8bits en r,g,b 16bits
      !paddsw xmm1,xmm0  ; addition signée (-32767 a 32768 ) ; si var=(a-+b) if var<-32767 : var= -32767 :  if var>32768 : var = 32768
      !packuswb xmm1,xmm1 ; converti r,g,b 16bits en rgb 8bits de 0 a 255 : if var<0 : var =0 : if var >255 : var =255
      !movq [rdi+rcx],xmm1
      !add rcx,8
      !dec rdx
  !jnz Filter_Brightness_1
  Rest_reg()
  DisableASM
EndProcedure

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

UseJPEGImageDecoder()
UsePNGImageDecoder()
Global imgx=1200
Global imgy=800


If OpenWindow(0, 0, 0, imgx, imgy, "balance", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  Define source.q , cible.q , t.q , file$ , i , var
 
  ScrollBarGadget(1, imgx/4, 1, imgx/2, 24, 0, 720, 25)
  ScrollBarGadget(2, imgx/4, 25, imgx/2, 24, 0, 512, 25)
  SetGadgetState(2, 256)
 
   file$ = OpenFileRequester("Image","","",0)
   source=10
   cible=20
   
   If Load_Image(source,file$) = 0 ; <- commande differente de "LOADIMAGE"
     MessageRequester("erreur", "image non chargeé" ,#PB_MessageRequester_Ok )
     End
   EndIf
   
   ResizeImage(source,imgx,imgy,#PB_Image_Smooth)
   
   CreateImage(cible,imgx,imgy,32) ; l'image doit entre en mode 32bits
   
   var=200
   SetGadgetState(1,var)
   Filter_bend(source,cible,var,var,var)
   
   Repeat
     Select WaitWindowEvent()

        Case  #PB_Event_CloseWindow
          End
        Case  #PB_Event_Gadget
         
          Select EventGadget()
             
            Case 1
              var=GetGadgetState(1)
              t=ElapsedMilliseconds()
              Filter_bend(source,cible,var,var,var) ; version asm
              ;Filter_bend_pb(source,cible,var,var,var) ; version pureabsic
              t=ElapsedMilliseconds()-t
             
            Case 2
              var=GetGadgetState(2)-256
              t=ElapsedMilliseconds()
              Filter_Brightness(source,cible,var,var,var)
              t=ElapsedMilliseconds()-t
             
          EndSelect
      EndSelect
       
       StartDrawing(WindowOutput(0))
       DrawImage(ImageID(cible),0,50)
       DrawText(5,50,"temps : "+Str(t))
       DrawText(5,5,Str(GetGadgetState(1))+"     ")
       DrawText(5,25,Str(GetGadgetState(2)-256)+"     ")
       StopDrawing()
   
    ForEver 
EndIf
Dernière modification par manababel le mer. 29/juil./2020 18:17, modifié 1 fois.
Avatar de l’utilisateur
SPH
Messages : 4721
Inscription : mer. 09/nov./2005 9:53

Re: filtre brightness - bend

Message par SPH »

Hmmmmm, je me mefis des codes du premier venu contenant de l'asm...

Perso, je ne testerais pas. Désolé :idea:

Mais, bravo si c'est toi qui 'a codé !!
http://HexaScrabble.com/
!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Intel Core i7 4770 64 bits - GTX 650 Ti
Version de PB : 6.00 - 64 bits
Avatar de l’utilisateur
Ar-S
Messages : 9472
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: filtre brightness - bend

Message par Ar-S »

Ce n'est pas le 1er code qu'il poste non plus...
Moi j'ai testé et c'est très réactif.
~~~~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 : 135
Inscription : jeu. 14/mai/2020 7:40

Re: filtre brightness - bend

Message par manababel »

Dans ce programme, il y a 3 procédures.
-Filter_bend_pb
-Filter_bend
-Filter_Brightness

Filter_bend_pb est écrite en basic
Filter_bend et Filter_bend_pb font la meme chose
Filter_Brightness, c'est juste :
r=r+val1
g=g+val2
b=b+val3

Si vous avez une image en 32 bits, vous pouvez supprimer toutes les parties en asm et tester seulement la procédure Filter_bend_Pb.

Filter_bend_ pb est juste posté à titre de comparaison
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: filtre brightness - bend

Message par falsam »

@SPH : Ben dit donc Monsieur SPH veux tu être aimable s'il te plait ? :wink:

@manababel : Je ne connais rien en Assembleur. Alors bravo pour l'énergie déployée pour ce code.

■ J'ai testé avec avec des photos récentes de 10 Mo environ. Les modifications appliquées sont immédiates. Par contre j'ai des soucis de resize avec des photos de 2010 et certaines passent en dégradés de gris à l'ouverture de la photo.

■ Un souci mineur. Crash de l'exécutable si on ne choisit pas d'image.
Configuration : Windows 11 Famille 64-bit - PB 6.03 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
manababel
Messages : 135
Inscription : jeu. 14/mai/2020 7:40

Re: filtre brightness - bend

Message par manababel »

j'ai corrigé le code, il ne devrait plus avoir d'erreur si on ne choisit pas de photo .

je ne comprends pas d'où viens le problème avec la photo qui passe en dégradé de gris.

Dans le doc de purebasic, "loadimage" convertit les images en 24 ou 32 bits.
la partie de mon programme ne convertit que les images 24 bits en 32 bits.
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: filtre brightness - bend

Message par falsam »

Je vais te passer une des photos et le résultat que j'obtiens avec ton code en mp
Configuration : Windows 11 Famille 64-bit - PB 6.03 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
manababel
Messages : 135
Inscription : jeu. 14/mai/2020 7:40

Re: filtre brightness - bend

Message par manababel »

Effectivement il y a un problème avec l'image que vous m'avez envoyée.
Je pense que le problème vient du fait que votre image ne soit pas un multiple de 2.
Il se peut que "createimage" ne crée que des images multiples de 2.

voici la partie à remplacé pour que ça fonctionne votre image

Code : Tout sélectionner

;-------------------------------------------------------------------
Procedure load_image(nom,file$)
  Protected source_p , cible_p , s.q
  Protected lg.q , ht.q , taille.q , depth.q , lg1.q

  LoadImage(nom,file$)
  If Not IsImage(nom) : ProcedureReturn 0 : EndIf
   
  StartDrawing(ImageOutput(nom))
  source_p = DrawingBuffer()
  ht = ImageHeight(nom)
  lg = ImageWidth(nom)
  Depth=OutputDepth()
  StopDrawing()

  If Depth=24
    taille=lg*ht
    cible_p=AllocateMemory(taille*4)
    Dim save.q(4)
    s=@save()
    EnableASM
      Save_reg()
      !mov rcx,[p.v_source_p]
      !mov rdx,[p.v_cible_p]
      !mov r8,[p.v_taille]
      !sub r8,1 ; <---------------- ????
      !copy_boucle24:
        !mov eax,[rcx]     
        !mov [rdx],eax
        !add rcx,3
        !add rdx,4
        !dec r8
       !jnz copy_boucle24
      Rest_Reg()
    DisableASM
    FreeArray(save())
   
    FreeImage(nom) ; supprime l'image 24bits
    
    lg1=lg ; test si l'image est un miltiple de 2
    lg1 = lg1 / 2
    lg1 = lg1 * 2
    If lg1 <> lg
      CreateImage(nom,lg+1,ht,32)
    Else
      CreateImage(nom,lg,ht,32)
    EndIf
    
    StartDrawing(ImageOutput(nom))
    source_p = DrawingBuffer()
    StopDrawing()
   
    CopyMemory( cible_p , source_p , taille*4 )
    FreeMemory(cible_p)
  EndIf
 
  ProcedureReturn 1
EndProcedure
Avatar de l’utilisateur
Kwai chang caine
Messages : 6962
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: filtre brightness - bend

Message par Kwai chang caine »

Bonjour Manababel, toujours impressionné par l'ASM que je ne connais pas, j'ai essayé le code que tu as eu la gentillesse de nous donner

Code : Tout sélectionner

For i=0 To 255
Et j'ai l'erreur que la boucle for ne supporte pas les variables de type quad :|
Surement une histoire de X64 / X86
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
manababel
Messages : 135
Inscription : jeu. 14/mai/2020 7:40

Re: filtre brightness - bend

Message par manababel »

Bonjour Kwai chang caine ,

Oui ce programme est en 64 bits.
Je peux 'récrire' en 32 bits si vous voulez ?
Avatar de l’utilisateur
Kwai chang caine
Messages : 6962
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: filtre brightness - bend

Message par Kwai chang caine »

C'est gentil, mais ne perd pas ton temps si tu n'en a pas besoin 8)
Je me doutais un peu de la réponse car avec l'ASM c'est souvent ça, mais j'ai ma réponse c'est le principal :wink:

J'adore tester les codes, même si ils ne me serviront peut être jamais :oops:
Surtout en ASM que j'admire depuis que j'ai appris qu'il existait et ce qu'il pouvait faire :wink:
Parfois ça peut aider le développeur (si ça ne fonctionne pas chez moi par exemple) et en plus chaque code (ASM ou non) me passionne et m’enrichis un petit peu plus
J'suis un peu un des BETA testeurs des forums PB, enfin plus BETA que testeur d'ailleurs :mrgreen:

En tout cas bravo de pouvoir jouer avec le "Langage des langages", ils auraient du l’appeler le LDL d'ailleurs :lol:
Encore merci de ton travail et partage 8)
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Répondre