PureBasic

Forums PureBasic
Nous sommes le Jeu 25/Fév/2021 9:28

Heures au format UTC + 1 heure




Poster un nouveau sujet Répondre au sujet  [ 4 messages ] 
Auteur Message
 Sujet du message: rotation d'image
MessagePosté: Mar 13/Oct/2020 15:57 
Hors ligne

Inscription: Jeu 14/Mai/2020 7:40
Messages: 66
Se programme permet de faire une rotation d'une image de 0 à 360 degrés.

Code:
EnableExplicit

Global Dim Reg_memory.q(4*344)

;-------------------------------------------------------------------
; sauvegarde de registres
Macro Save_reg()
  Protected s.q
  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



; 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

EndMacro

;-------------------------------------------------------------------
;--version purebasic
Procedure Filter_Rotate_pb(source,cible,angle)
  Protected degres.f , c1.f , s1.f , x3.f , y3.f
  Protected x.l , y.l, xx.l , yy.l , var.l
  Protected pos.q
 
  sp(source,cible)
 
  degres.f=angle*#PI/180
  c1.f=Cos(degres)
  s1.f=Sin(degres)
  x3.f=lg/2
  y3.f=ht/2
 
  For y=0 To ht-1
    pos=(cible_p+(lg*y)*4)
    For x=0 To lg-1   
      xx.l=x3+ ((x-x3) * c1) + (y-y3)* s1
      yy.l=y3- ((x-x3) * s1) + (y-y3)* c1
      If (xx<0) Or (xx>lg-1) Or (yy<0) Or (yy>ht-1)
        PokeL(pos+x*4,0) ; fond noir
      Else
        var=PeekL(source_p+(yy*lg*4)+xx*4)
        PokeL(pos+x*4,var)
      EndIf     
    Next
  Next

EndProcedure

;-------------------------------------------------------------------
;--version asm
Procedure Filter_Rotate_asm(source,cible,angle)
    Save_reg()
  Protected degres.f , c1.f , s1.f , x3.f , y3.f
  sp(source,cible)
 
  degres=angle*#PI/180
  c1=Cos(degres)
  s1=Sin(degres)
  x3=lg/2
  y3=ht/2
 
  !INSERTPS xmm1,[p.v_x3],$10 ; x3
  !INSERTPS xmm1,[p.v_y3],$00 ; y3
  ; xmm1 = x3 y3
  !INSERTPS xmm2,[p.v_c1],$10 ; c1
  !INSERTPS xmm2,[p.v_s1],$00 ; s1
  ; xmm2 = c1 s1
  !INSERTPS xmm3,[p.v_s1],$10 ; s1
  !INSERTPS xmm3,[p.v_c1],$00 ; c1
  ; xmm3 = s1 c1
 
  !xor r11,r11
  !xor r10,r10 ; For y=0 To ht-1
  !boucle_y:   
    !xor r9,r9 ; For x=0 To lg-1
    !boucle_x:
      ;xx=  x3 + ( ( x - x3 ) * c1 )    +   ( ( y - y3 ) * s1 )
      ;yy=  y3 - ( ( x - x3 ) * s1 )    +   ( ( y - y3 ) * c1 )
      !movq xmm4,r9;[p.v_x]
      !CVTDQ2PS xmm4,xmm4 ; xmm4 = float(x)
      !movq xmm5,r10;[p.v_y]
      !CVTDQ2PS xmm5,xmm5 ; xmm5 = float(y)
      !subss xmm4,[p.v_x3]; (x-x3)
      !subss xmm5,[p.v_y3]; (y-y3)
      !VBROADCASTSS xmm4,xmm4 ; (x-x3)         (x-x3)
      !VBROADCASTSS xmm5,xmm5 ; (y-y3)         (y-y3)
      !mulps xmm4,xmm2 ;        (x-x3)*c1      (x-x3)*s1
      !mulps xmm5,xmm3 ;        (y-y3)*s1      (y-y3)*c1
      !ADDSUBPS xmm4,xmm5 ; (x-x3)*c1+(y-y3)*s1       (x-x3)*s1-(y-y3)*c1
      !movups xmm5,xmm1
      !ADDSUBPS xmm5,xmm4 ; x3+(x-x3)*c1+(y-y3)*s1       y3-(x-x3)*s1-(y-y3)*c1
      !CVTPS2DQ xmm5,xmm5 ; xmm5 = int(xmm5)
     
      !xor rax,rax
      !PEXTRD eax,xmm5,0
      !mov r13,rax ; r13 = yy
      !xor rax,rax
      !PEXTRD eax,xmm5,1
      !mov r12,rax ; r12 = xx
   
      !mov ecx,0 ; var = 0 = couleur  noir
     
      !cmp r12,[p.v_lg] ; if xx>=lg : goto 'saut'
      !jge saut
      ;!cmp r12,0 ; if xx<0 : goto 'saut'
      ;!jl saut
      !cmp r13,[p.v_ht]  ; if yy>=ht : goto 'saut'
      !jge saut
      ;!cmp r13,0 ; if yy<0 : goto 'saut'
      ;!jl saut
     
        !mov r8,r13;[p.v_yy] ;var = PeekL(source_p+((yy*lg)+xx)*4)
        !iMUL r8,[p.v_lg]
        !add r8,r12;[p.v_xx]
        !shl r8,2
        !add r8,[p.v_source_p]
        !mov ecx,[r8]
       
      !saut:       
     
      !mov rdx,r11 ; pos=(cible_p+(lg*y)*4)
      !shl rdx,2
      !add rdx,[p.v_cible_p]
      !mov rax,r9 ; PokeL(pos+x*4,var)
      !shl rax,2
      !add rax,rdx
      !mov [rax],ecx
     
    !inc r9 ; x=x-1
    !cmp r9,[p.v_lg]
    !jb boucle_x ; Next x
   
  !add r11,[p.v_lg] ; 'lg*y'
  !inc r10 ; xyx+1
  !cmp r10,[p.v_ht]
  !jb boucle_y ; next y

  Rest_Reg()
EndProcedure

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

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


If OpenWindow(0, 0, 0, imgx, imgy+16, "Rotate", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  Define source.q , cible.q , t.q , file$ , i , angle.l , mem_angle.l

   file$ = OpenFileRequester("Image","","",0)
   source=10
   cible=20
   
   If Not Load_Image(source,file$) ; <- commande differente de "LOADIMAGE"
     MessageRequester("load_image","erreur de chargement",#PB_MessageRequester_Ok | #PB_MessageRequester_Error)
     End
   EndIf
   
   ScrollBarGadget(1, 0, 0, 1200, 16, 0, 360, imgx/360 ) 
   
   ResizeImage(source,imgx,imgy,#PB_Image_Smooth)
   
   CreateImage(cible,imgx,imgy,32) ; l'image doit entre en mode 32bits
   
   mem_angle=1
   Repeat
     angle=GetGadgetState(1)
     If angle<>mem_angle
       t=ElapsedMilliseconds()
       angle=GetGadgetState(1)
         Filter_Rotate_pb(source,cible,angle) ; <--- par defaut , version purebasic
       t=ElapsedMilliseconds()-t
       StartDrawing(WindowOutput(0))
       DrawImage(ImageID(cible),0,16)
       DrawText(5,5+16,Str(t))
       StopDrawing()
       mem_angle = angle
     EndIf
     
   Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf




Haut
 Profil  
Répondre en citant le message  
 Sujet du message: Re: rotation d'image
MessagePosté: Mar 13/Oct/2020 21:25 
Hors ligne
Avatar de l’utilisateur

Inscription: Dim 22/Aoû/2010 15:24
Messages: 6935
Localisation: IDF (Yvelines)
Très bien ce code. Merci :wink:

_________________

➽ Config PureBasic : Windows 10 Version 64 Bits - DirectX 11 - PB 5.72

➽ Je ne réponds pas aux MP techniques


Haut
 Profil  
Répondre en citant le message  
 Sujet du message: Re: rotation d'image
MessagePosté: Mer 14/Oct/2020 22:18 
Hors ligne
Avatar de l’utilisateur

Inscription: Jeu 25/Juin/2015 16:18
Messages: 352
tu peux aussi écrire ta fonction comme ça:
je pense que c'est plus rapide, juste 2 additions par pixel (et 2 conversions en int)

Code:
Procedure Filter_Rotate_pb(source,cible,angle)
    Protected degres.f , c1.f , s1.f , x3.f , y3.f
    Protected x.l , y.l, var.l
    Protected.f xx , yy
    Protected pos.q
   
    sp(source,cible)
   
    degres.f=angle*#PI/180
    c1.f=Cos(degres)
    s1.f=Sin(degres)
    x3.f=lg/2
    y3.f=ht/2
   
    For y=0 To ht-1
        pos=(cible_p+(lg*y)*4)
        xx=x3 -x3 * c1 + (y-y3)* s1
        yy=y3 +x3 * s1 + (y-y3)* c1
        For x=0 To lg-1   
            If (xx<0) Or (xx>lg-1) Or (yy<0) Or (yy>ht-1)
                PokeL(pos+x*4,0) ; fond noir
            Else
                var=PeekL(source_p+(Int(yy)*lg*4)+Int(xx)*4)
                PokeL(pos+x*4,var)
            EndIf     
            xx+c1
            yy-s1
        Next
    Next
EndProcedure


Haut
 Profil  
Répondre en citant le message  
 Sujet du message: Re: rotation d'image
MessagePosté: Jeu 15/Oct/2020 20:07 
Hors ligne

Inscription: Jeu 14/Mai/2020 7:40
Messages: 66
Bizarment en purebasic , il n'y a pas de différence de performance.
mais en Asm il y plus de 30% de différence.
merci pour le code.


Code:
Procedure Filter_Rotate_pb(source,cible,angle)
    Protected degres.f , c1.f , s1.f , x2.f , y2.f, x3.f , y3.f
    Protected x.l , y.l, var.l
    Protected.f xx , yy
    Protected pos.q
   
    sp(source,cible)
   
    degres.f=angle*#PI/180
    c1.f=Cos(degres)
    s1.f=Sin(degres)
    x3.f=lg/2
    y3.f=ht/2
    x2.f=(x3 * c1)
    y2.f=(x3 * s1)
   
    For y=0 To ht-1
        pos=(cible_p+(lg*y)*4)
        xx=x3 - (x2 - ((y-y3)* s1))
        yy=y3 + (y2 + ((y-y3)* c1))
        For x=0 To lg-1   
            If (xx<0) Or (xx>lg-1) Or (yy<0) Or (yy>ht-1)
                PokeL(pos+x*4,0) ; fond noir
            Else
                var=PeekL(source_p+(Int(yy)*lg*4)+Int(xx)*4)
                PokeL(pos+x*4,var)
            EndIf     
            xx+c1
            yy-s1
        Next
    Next
EndProcedure




Code:
Procedure Filter_Rotate_asm(source,cible,angle)
    Save_reg()
  Protected degres.f , c1.f , s1.f , x2.f , y2.f , x3.f , y3.f
  sp(source,cible)

  degres=angle*#PI/180
  c1=Cos(degres)
  s1=Sin(degres)
  x3=lg/2
  y3=ht/2
  x2.f=(x3 * c1)
  y2.f=(x3 * s1)
 
  !xor r15,r15
  !xor r14,r14
 
  !movss xmm12,[p.v_c1]
  !movss xmm13,[p.v_s1]

  !INSERTPS xmm1,[p.v_x3],$00 ; x3
  !INSERTPS xmm1,[p.v_y3],$10 ; y3
  ; xmm1 = y3 x3
  !INSERTPS xmm2,[p.v_s1],$00 ; s1
  !INSERTPS xmm2,[p.v_c1],$10 ; c1
  ; xmm2 = c1 s1
  !INSERTPS xmm3,[p.v_x2],$00 ; x2
  !INSERTPS xmm3,[p.v_y2],$10 ; y2
  ; xmm3 = y2 x2

  !xor r11,r11
  !xor r10,r10 ; For y=0 To ht-1
  !boucle_y:   
    ;xx=x3 - (x2 - ((y-y3)* s1))
    ;yy=y3 + (y2 + ((y-y3)* c1))
    !movq xmm4,r10;[p.v_y]
    !CVTDQ2PS xmm4,xmm4 ; xmm4 = float(y) 
    !subss xmm4,[p.v_y3]; (y-y3)
    !INSERTPS xmm4,xmm4,$10 ; (y-y3)         (y-y3)
    !mulps xmm4,xmm2 ;        (y-y3)*c1      (y-y3)*s1
    !movups xmm5,xmm3 ;          y2             x2
    !ADDSUBPS xmm5,xmm4 ;    y2+((y-y3)*c1)   x2-((y-y3)*s1)
    !movups xmm4,xmm1  ;           y3               x3
    !ADDSUBPS xmm4,xmm5 ;  y3+(y2+(y-y3)*c1)    x3-(x2-(y-y3)*s1)
       
    !INSERTPS xmm6,xmm4,$10
    !INSERTPS xmm6,xmm4,$40
   
    !xor r9,r9 ; For x=0 To lg-1   
    !boucle_x: 
   
      !CVTPS2DQ xmm5,xmm6 ; xmm5 = int(xmm6)
      !xor rax,rax
      !PEXTRD eax,xmm5,0
      !mov r13,rax ; r13 = yy
      !xor rax,rax
      !PEXTRD eax,xmm5,1
      !mov r12,rax ; r12 = xx
   
      !mov ecx,0 ; var = 0 = couleur  noir
      !cmp r12,[p.v_lg] ; if xx>=lg : goto 'saut'
      !jge saut
      !cmp r12,0 ; if xx<0 : goto 'saut'
      !jl saut
      !cmp r13,[p.v_ht]  ; if yy>=ht : goto 'saut'
      !jge saut
      !cmp r13,0 ; if yy<0 : goto 'saut'
      !jl saut
        !mov r8,r13;[p.v_yy] ;var = PeekL(source_p+((yy*lg)+xx)*4)
        !iMUL r8,[p.v_lg]
        !add r8,r12;[p.v_xx]
        !shl r8,2
        !add r8,[p.v_source_p]
        !mov ecx,[r8]
      !saut:       
      !mov rdx,r11 ; pos=(cible_p+(lg*y)*4)
      !shl rdx,2
      !add rdx,[p.v_cible_p]
      !mov rax,r9 ; PokeL(pos+x*4,var)
      !shl rax,2
      !add rax,rdx
      !mov [rax],ecx
     
      !ADDSUBPS xmm6,xmm2
     
    !inc r9 ; x=x+1
    !cmp r9,[p.v_lg]
    !jb boucle_x ; Next x
   
  !add r11,[p.v_lg] ; 'lg*y'
  !inc r10 ; y=y+1
  !cmp r10,[p.v_ht]
  !jb boucle_y ; next y

  Rest_Reg()
EndProcedure


Haut
 Profil  
Répondre en citant le message  
Afficher les messages postés depuis:  Trier par  
Poster un nouveau sujet Répondre au sujet  [ 4 messages ] 

Heures au format UTC + 1 heure


Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 2 invités


Vous ne pouvez pas poster de nouveaux sujets
Vous ne pouvez pas répondre aux sujets
Vous ne pouvez pas éditer vos messages
Vous ne pouvez pas supprimer vos messages

Rechercher:
Aller à:  

 


Powered by phpBB © 2008 phpBB Group | Traduction par: phpBB-fr.com
subSilver+ theme by Canver Software, sponsor Sanal Modifiye