Page 3 sur 8

Publié : sam. 12/févr./2005 20:44
par erix14
Du coup, je demande si il ne serai pas interressant d'optimiser avec de l'assembleur ma lib.
Est-ce que des pros de l'assembleur seraient partant ?
Oui, je veux bien le faire :D

Publié : sam. 12/févr./2005 21:07
par Le Soldat Inconnu
ok ;)

voici un exemple qui permet de tester la rapidité de la rotation et son bon fonctionnement.
La procedure qui permet la rotation est au début. y'a plus qu'à l'optimiser et voir le résultat :wink:

Code : Tout sélectionner

ProcedureDLL.l RotateImage2(ImageID, Angle.l) ; Rotation d'une image d'un angle multiple de 90°
  Protected bmi.BITMAPINFO, Hdc.l, NewImageID, Mem, n, nn, bm.BITMAP, Temp1, Temp2
  
  NewImageID = 0
  
  If Angle <= 0
    Angle = 360 + Angle
  EndIf
  
  ; On récupère la taille de l'image
  GetObject_(ImageID, SizeOf(BITMAP), @bm.BITMAP)
  
  If Angle = 90 Or Angle = 180 Or Angle = 270

    ; on prépare les infos pour récupérer l'image sous forme d'adresse mémoire
    bmi\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
    bmi\bmiHeader\biWidth = bm\bmWidth
    bmi\bmiHeader\biHeight = bm\bmHeight
    bmi\bmiHeader\biPlanes = 1
    bmi\bmiHeader\biBitCount = 32
    bmi\bmiHeader\biCompression = #BI_RGB
    
    ; On alloue 2 espace mémoire pour recevoir l'image d'origine et l'image pivotée
    Mem = AllocateMemory(bm\bmWidth * bm\bmHeight * 4)
    If Mem
      Mem2 = AllocateMemory(bm\bmWidth * bm\bmHeight * 4)
      If Mem2
        
        ; On récupère l'image dans un espace mémoire
        Hdc = CreateCompatibleDC_(GetDC_(ImageID))
        If Hdc
          GetDIBits_(Hdc, ImageID, 0, bm\bmHeight, Mem, @bmi, #DIB_RGB_COLORS) ; on envoie la liste dans l'image
          ReleaseDC_(0, Hdc)
        EndIf
        
        ; On fait la rotation de l'image de 90, 180 ou 270°
        Select Angle
          Case 90 ; rotation de 90°
            Temp1 = bm\bmWidth - 1
            ; Pour chaque point de l'image
            For n = 0 To bm\bmHeight - 1
              For nn = 0 To Temp1
                PokeL(Mem2 + (n + (Temp1 - nn) * bm\bmHeight) * 4, PeekL(Mem + (nn + n * bm\bmWidth) * 4)) ; On fait une rotation de 90°
                ; Le * 4 vient du fait qu'on manipule des long
              Next
            Next
            ; On inverse la largeur et la hauteur de l'image
            Temp1 = bm\bmHeight : bm\bmHeight = bm\bmWidth : bm\bmWidth = Temp1
            bmi\bmiHeader\biWidth = bm\bmWidth
            bmi\bmiHeader\biHeight = bm\bmHeight
            ; On crée la nouvelle image vierge
            NewImageID = CreateImage(#PB_Any, bm\bmWidth, bm\bmHeight)
            
          Case 180
            Temp1 = Mem2 + bm\bmWidth * bm\bmHeight * 4 - 4
            For n = 0 To bm\bmHeight - 1
              For nn = 0 To bm\bmWidth - 1
                Temp2 = (nn + n * bm\bmWidth) * 4
                PokeL(Temp1 - Temp2, PeekL(Mem + Temp2))
              Next
            Next
            NewImageID = CreateImage(#PB_Any, bm\bmWidth, bm\bmHeight)
            
          Case 270
            Temp1 = bm\bmHeight - 1
            For n = 0 To Temp1
              For nn = 0 To bm\bmWidth - 1
                PokeL(Mem2 + (Temp1 - n + nn * bm\bmHeight) * 4, PeekL(Mem + (nn + n * bm\bmWidth) * 4))
              Next
            Next
            Temp1 = bm\bmHeight : bm\bmHeight = bm\bmWidth : bm\bmWidth = Temp1
            bmi\bmiHeader\biWidth = bm\bmWidth
            bmi\bmiHeader\biHeight = bm\bmHeight
            NewImageID = CreateImage(#PB_Any, bm\bmWidth, bm\bmHeight)
            
        EndSelect
        
        ; On copie l'espace mémoire qui contient l'image pivotée dans la nouvelle image créée
        Hdc = CreateCompatibleDC_(GetDC_(ImageID()))
        If Hdc
          SetDIBits_(Hdc, ImageID(), 0, bm\bmHeight, Mem2, @bmi, #DIB_RGB_COLORS) ; on envoie la liste dans l'image
          ReleaseDC_(0, Hdc)
        EndIf
        
        ; On libère la mémoire
        FreeMemory(Mem2)
      EndIf
      FreeMemory(Mem)
    EndIf
    
  ElseIf Angle = 360
    NewImageID = CreateImage(#PB_Any, bm\bmWidth, bm\bmHeight)
    StartDrawing(ImageOutput())
      DrawImage(ImageID, 0, 0)
    StopDrawing()
  EndIf
  
  ProcedureReturn NewImageID
EndProcedure



;-----------------------------------------
;- Test de rapidité

ImageOrigine = CreateImage(0, 1000, 1000)
StartDrawing(ImageOutput())
  For n = 0 To 999
    For nn = 0 To 999
      Plot(n, nn, Random($FFFFFF))
    Next
  Next
StopDrawing()
Dim Liste(ImageWidth() - 1, ImageHeight() - 1)

#NbTest = 5

Temps1 = ElapsedMilliseconds()

For n = 1 To #NbTest
  ;- Test de rapidité sur la rotation et la symétrie d'image
  ; ImageModifiee = ImageSymmetryH(ImageOrigine)
  ; ImageModifiee = ImageSymmetryV(ImageOrigine)
  ; ImageModifiee = RotateImage(ImageOrigine, 180)
  ImageModifiee = RotateImage2(ImageOrigine, 90)
  ; ImageModifiee = RotateImage(ImageOrigine, 270)
  ; ImageModifiee = RotateImageEx(ImageOrigine, 30)
  ;- Test de rapidité sur le transfert d'image
  ; GetImageBits(UseImage(0), @Liste())
  ; SetImageBits(UseImage(0), @Liste())
Next

Temps2 = ElapsedMilliseconds()

Vitesse = (Temps2 - Temps1) / #NbTest
NbPixel = ImageHeight() * ImageWidth()

MessageRequester("Temps", Str(Vitesse) + " ms" + Chr(10) + "Image de " + Str(ImageWidth()) + " * " + Str(ImageHeight()) + " pixels" + Chr(10) + "Nb pixels traités = " + Str(NbPixel), 0)


;-----------------------------------------
;- Test  d'affichage d'image avec rotation
; On dessine une image
ImageNormale = CreateImage(#PB_Any, 80, 100)
StartDrawing(ImageOutput())
  Box(0, 0, 80, 100, $6F6F6F)
  Box(5, 5, 35, 45, $FF)
  Box(40, 5, 35, 45, $FF00)
  Box(5, 50, 35, 45, $FF0000)
  Box(40, 50, 35, 45, $FFFFFF)
StopDrawing()

; On fait différente rotation de cette image
ImageRotation90 = RotateImage2(UseImage(ImageNormale), 90) ; ou -270°
ImageRotation180 = RotateImage2(UseImage(ImageNormale), 180) ; ou -180°
ImageRotation270 = RotateImage2(UseImage(ImageNormale), 270) ; ou -90°
; RotateImage(ImageID.l, Angle.l)
; ImageID : Handle de l'image
; Angle : Angle de rotation en dégré, les valeurs suivantes sont acceptées : -270, -180, -90, 0, 90, 180, 270, 360
; La fonction retourne l'identifiant PB de la nouvelle image, pas le handle de la nouvelle image, le but étant de pouvoir manipuler cette nouvelle image comme une image PB

; Création de la fenêtre et de la GadgetList
If OpenWindow(0, 0, 0, 250, 300, #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget, "Effect - Rotation d'image") = 0 Or CreateGadgetList(WindowID()) = 0
  End
EndIf

TextGadget(#PB_Any, 10, 10, 100, 15, "Image normale")
ImageGadget(#PB_Any, 10, 25, 0, 0, UseImage(ImageNormale))

TextGadget(#PB_Any, 120, 10, 100, 15, "Rotation de 90°")
ImageGadget(#PB_Any, 120, 25, 0, 0, UseImage(ImageRotation90))

TextGadget(#PB_Any, 10, 135, 100, 15, "Rotation de 180°")
ImageGadget(#PB_Any, 10, 150, 0, 0, UseImage(ImageRotation180))

TextGadget(#PB_Any, 120, 135, 100, 15, "Rotation de 270°")
ImageGadget(#PB_Any, 120, 150, 0, 0, UseImage(ImageRotation270))

Repeat
  Event = WaitWindowEvent()
  
Until Event = #PB_EventCloseWindow

End

Publié : dim. 13/févr./2005 9:54
par erix14
Voilà c'est fait :D
le traitement graphique est beaucoup plus rapide, mais le problème c'est la lenteur des fonctions API (GetDIBits_,SetDIBits_,...) que je ne peux pas optimiser. Pour avoir un résultat flagrant, il faudrait un traitement graphique "plus lourd"...

Code : Tout sélectionner

ProcedureDLL.l RotateImage2(ImageID, Angle.l) ; Rotation d'une image d'un angle multiple de 90° 
          Protected bmi.BITMAPINFO, Hdc.l, NewImageID, n, nn, bm.BITMAP, Temp1, Temp2 
          Global Mem,Mem2,pMem,Largeur,Largeur4,Longueur,Longueur4
          NewImageID = 0 
          
          If Angle <= 0 
                    Angle = 360 + Angle 
          EndIf 
          
          ; On récupère la taille de l'image 
          GetObject_(ImageID, SizeOf(BITMAP), @bm.BITMAP) 
          
          If Angle = 90 Or Angle = 180 Or Angle = 270 
                    
                    ; on prépare les infos pour récupérer l'image sous forme d'adresse mémoire 
                    bmi\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER) 
                    bmi\bmiHeader\biWidth = bm\bmWidth 
                    bmi\bmiHeader\biHeight = bm\bmHeight 
                    bmi\bmiHeader\biPlanes = 1 
                    bmi\bmiHeader\biBitCount = 32 
                    bmi\bmiHeader\biCompression = #BI_RGB 
                    
                    ; On alloue 2 espace mémoire pour recevoir l'image d'origine et l'image pivotée 
                    Mem = AllocateMemory(bm\bmWidth * bm\bmHeight * 4) 
                    If Mem 
                              Mem2 = AllocateMemory(bm\bmWidth * bm\bmHeight * 4) 
                              If Mem2 
                                        
                                        ; On récupère l'image dans un espace mémoire 
                                        Hdc = CreateCompatibleDC_(GetDC_(ImageID)) 
                                        If Hdc 
                                                  GetDIBits_(Hdc, ImageID, 0, bm\bmHeight, Mem, @bmi, #DIB_RGB_COLORS) ; on envoie la liste dans l'image 
                                                  ReleaseDC_(0, Hdc) 
                                        EndIf 
                                        
                                        ; On fait la rotation de l'image de 90, 180 ou 270° 
                                        Select Angle 
                                                  Case 90 ; rotation de 90° 
                                                            ;/
                                                            Longueur = bm\bmWidth
                                                            Largeur = bm\bmHeight
                                                            Largeur4 = bm\bmHeight * 4
                                                            pMem = Mem2 - Largeur4 + ( bm\bmWidth * bm\bmHeight ) * 4
                                                            ; Pour chaque point de l'image
                                                            !MOV   ebx,dword [v_Mem]
                                                            !MOV   eax,dword [v_pMem]
                                                            !MOV   ecx,dword [v_Largeur]
                                                            !Encore90Y:
                                                                      !PUSH    ecx
                                                                      !PUSH    eax
                                                                      !MOV     ecx,dword [v_Longueur]
                                                                      !Encore90X:
                                                                                !MOV    edx,dword[ebx]
                                                                                !MOV    dword[eax],edx
                                                                                !ADD     ebx,4
                                                                                !SUB     eax,dword [v_Largeur4]
                                                                                !DEC     ecx
                                                                      !JNZ Encore90X
                                                                      !POP eax
                                                                      !ADD eax,4
                                                                      !POP ecx
                                                                      !DEC ecx
                                                            !JNZ Encore90Y 
                                                            ;/
                                                            
                                                            ; On inverse la largeur et la hauteur de l'image 
                                                            Temp1 = bm\bmHeight : bm\bmHeight = bm\bmWidth : bm\bmWidth = Temp1 
                                                            bmi\bmiHeader\biWidth = bm\bmWidth 
                                                            bmi\bmiHeader\biHeight = bm\bmHeight 
                                                            ; On crée la nouvelle image vierge 
                                                            NewImageID = CreateImage(#PB_Any, bm\bmWidth, bm\bmHeight) 
                                                            
                                                  Case 180 
                                                            ;/
                                                            Longueur = bm\bmWidth
                                                            Largeur = bm\bmHeight
                                                            Longueur4 = bm\bmWidth * 4
                                                            pMem = Mem2 + ( bm\bmWidth * bm\bmHeight ) * 4 - 4
                                                            ; Pour chaque point de l'image
                                                            !MOV   ebx,dword [v_Mem]
                                                            !MOV   eax,dword [v_pMem]
                                                            !MOV   ecx,dword [v_Largeur]
                                                            !Encore180Y:
                                                                      !PUSH    ecx
                                                                      !PUSH    eax
                                                                      !MOV     ecx,dword [v_Longueur]
                                                                      !Encore180X:
                                                                                !MOV    edx,dword[ebx]
                                                                                !MOV    dword[eax],edx
                                                                                !ADD     ebx,4
                                                                                !SUB     eax,4
                                                                                !DEC     ecx
                                                                      !JNZ Encore180X
                                                                      !POP eax
                                                                      !SUB eax,dword [v_Longueur4]
                                                                      !POP ecx
                                                                      !DEC ecx
                                                            !JNZ Encore180Y 
                                                            ;/
                                                            NewImageID = CreateImage(#PB_Any, bm\bmWidth, bm\bmHeight) 
                                                            
                                                  Case 270 
                                                            ;/
                                                            Longueur = bm\bmWidth
                                                            Largeur = bm\bmHeight
                                                            Largeur4 = bm\bmHeight * 4
                                                            pMem = Mem2 + Largeur4 - 4
                                                            ; Pour chaque point de l'image
                                                            !MOV   ebx,dword [v_Mem]
                                                            !MOV   eax,dword [v_pMem]
                                                            !MOV   ecx,dword [v_Largeur]
                                                            !Encore270Y:
                                                                      !PUSH    ecx
                                                                      !PUSH    eax
                                                                      !MOV     ecx,dword [v_Longueur]
                                                                      !Encore270X:
                                                                                !MOV    edx,dword[ebx]
                                                                                !MOV    dword[eax],edx
                                                                                !ADD     ebx,4
                                                                                !ADD     eax,dword [v_Largeur4]
                                                                                !DEC     ecx
                                                                      !JNZ Encore270X
                                                                      !POP eax
                                                                      !SUB eax,4
                                                                      !POP ecx
                                                                      !DEC ecx
                                                            !JNZ Encore270Y 
                                                            ;/
                                                            Temp1 = bm\bmHeight : bm\bmHeight = bm\bmWidth : bm\bmWidth = Temp1 
                                                            bmi\bmiHeader\biWidth = bm\bmWidth 
                                                            bmi\bmiHeader\biHeight = bm\bmHeight 
                                                            NewImageID = CreateImage(#PB_Any, bm\bmWidth, bm\bmHeight) 
                                                            
                                        EndSelect 
                                        
                                        ; On copie l'espace mémoire qui contient l'image pivotée dans la nouvelle image créée 
                                        Hdc = CreateCompatibleDC_(GetDC_(ImageID())) 
                                        If Hdc 
                                                  SetDIBits_(Hdc, ImageID(), 0, bm\bmHeight, Mem2, @bmi, #DIB_RGB_COLORS) ; on envoie la liste dans l'image 
                                                  ReleaseDC_(0, Hdc) 
                                        EndIf 
                                        
                                        ; On libère la mémoire 
                                        FreeMemory(Mem2) 
                              EndIf 
                              FreeMemory(Mem) 
                    EndIf 
                    
          ElseIf Angle = 360 
                    NewImageID = CreateImage(#PB_Any, bm\bmWidth, bm\bmHeight) 
                    StartDrawing(ImageOutput()) 
                    DrawImage(ImageID, 0, 0) 
                    StopDrawing() 
          EndIf 
          
          ProcedureReturn NewImageID 
EndProcedure 



;----------------------------------------- 
;- Test de rapidité 

ImageOrigine = CreateImage(0, 1000, 1000) 
StartDrawing(ImageOutput()) 
For n = 0 To 999 
          For nn = 0 To 999 
                    Plot(n, nn, Random($FFFFFF)) 
          Next 
Next 
StopDrawing() 
Dim Liste(ImageWidth() - 1, ImageHeight() - 1) 

#NbTest = 5 

Temps1 = ElapsedMilliseconds() 

For n = 1 To #NbTest 
          ;- Test de rapidité sur la rotation et la symétrie d'image 
          ; ImageModifiee = ImageSymmetryH(ImageOrigine) 
          ; ImageModifiee = ImageSymmetryV(ImageOrigine) 
          ; ImageModifiee = RotateImage(ImageOrigine, 180) 
          ImageModifiee = RotateImage2(ImageOrigine, 90) 
          ; ImageModifiee = RotateImage(ImageOrigine, 270) 
          ; ImageModifiee = RotateImageEx(ImageOrigine, 30) 
          ;- Test de rapidité sur le transfert d'image 
          ; GetImageBits(UseImage(0), @Liste()) 
          ; SetImageBits(UseImage(0), @Liste()) 
Next 

Temps2 = ElapsedMilliseconds() 

Vitesse = (Temps2 - Temps1) / #NbTest 
NbPixel = ImageHeight() * ImageWidth() 

MessageRequester("Temps", Str(Vitesse) + " ms" + Chr(10) + "Image de " + Str(ImageWidth()) + " * " + Str(ImageHeight()) + " pixels" + Chr(10) + "Nb pixels traités = " + Str(NbPixel), 0) 


;----------------------------------------- 
;- Test  d'affichage d'image avec rotation 
; On dessine une image 
ImageNormale = CreateImage(#PB_Any, 80, 100) 
StartDrawing(ImageOutput()) 
Box(0, 0, 80, 100, $6F6F6F) 
Box(5, 5, 35, 45, $FF) 
Box(40, 5, 35, 45, $FF00) 
Box(5, 50, 35, 45, $FF0000) 
Box(40, 50, 35, 45, $FFFFFF) 
StopDrawing() 

; On fait différente rotation de cette image 
ImageRotation90 = RotateImage2(UseImage(ImageNormale), 90) ; ou -270° 
ImageRotation180 = RotateImage2(UseImage(ImageNormale), 180) ; ou -180° 
ImageRotation270 = RotateImage2(UseImage(ImageNormale), 270) ; ou -90° 
; RotateImage(ImageID.l, Angle.l) 
; ImageID : Handle de l'image 
; Angle : Angle de rotation en dégré, les valeurs suivantes sont acceptées : -270, -180, -90, 0, 90, 180, 270, 360 
; La fonction retourne l'identifiant PB de la nouvelle image, pas le handle de la nouvelle image, le but étant de pouvoir manipuler cette nouvelle image comme une image PB 

; Création de la fenêtre et de la GadgetList 
If OpenWindow(0, 0, 0, 250, 300, #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget, "Effect - Rotation d'image") = 0 Or CreateGadgetList(WindowID()) = 0 
          End 
EndIf 

TextGadget(#PB_Any, 10, 10, 100, 15, "Image normale") 
ImageGadget(#PB_Any, 10, 25, 0, 0, UseImage(ImageNormale)) 

TextGadget(#PB_Any, 120, 10, 100, 15, "Rotation de 90°") 
ImageGadget(#PB_Any, 120, 25, 0, 0, UseImage(ImageRotation90)) 

TextGadget(#PB_Any, 10, 135, 100, 15, "Rotation de 180°") 
ImageGadget(#PB_Any, 10, 150, 0, 0, UseImage(ImageRotation180)) 

TextGadget(#PB_Any, 120, 135, 100, 15, "Rotation de 270°") 
ImageGadget(#PB_Any, 120, 150, 0, 0, UseImage(ImageRotation270)) 

Repeat 
          Event = WaitWindowEvent() 
          
Until Event = #PB_EventCloseWindow 

End

Publié : dim. 13/févr./2005 11:14
par Le Soldat Inconnu
sur mon 900 mhz, j'ai pratiquement aucune différence de vitesse.
240 contre 250.

c'est pas flaggrant :( Sur des calcul simple, j'ai pas l'impression que l'ASM apporte beaucoup.

les fonctions de l'API prennent 186 ms donc les 3/4 du temps de calcul.

comme tu le dits, faut arriver à faire sauter l'API GetDIBits :)
Mais pour s'en passer, il faut trouver le moyen d'accéder à l'image en mémoire à partir de son handle. car passer par un startdrawing est nettement plus lent.
Quelqu'un à une idée ?


Par contre, sur un traitement avec plein de math, on doit avoir une grosse différence avec de l'ASM.

je vais te préparer un exemple pour la rotation d'une image avec un angle quelconque, la j'ai 4.3 secondes de calcul, on dervrait être bien plus gagnant

Publié : dim. 13/févr./2005 12:32
par nico
et en utilisant aucune fonction de Pure, que des API ?

Publié : dim. 13/févr./2005 12:44
par erix14
J'ai isolé les boucles des traitements graphiques pour voir les temps :

Code : Tout sélectionner

#NbTest = 5 
Global Mem,Mem2,pMem,Largeur,Largeur4,Longueur 
Longueur = 1000 
Largeur = 1000 

Mem = AllocateMemory(Longueur * Largeur * 4) 
If Mem 
          Mem2 = AllocateMemory(Longueur * Largeur * 4) 
          If Mem2 
                    ;/ rotation de 90° 
                    Temps1 = ElapsedMilliseconds() 
                    For t = 1 To #NbTest 
                              ;/ 
                              Largeur4 = Largeur * 4 
                              pMem = Mem2 - Largeur4 + ( Longueur * Largeur ) * 4 
                              ; Pour chaque point de l'image 
                              !MOV   ebx,dword [v_Mem] 
                              !MOV   eax,dword [v_pMem] 
                              !MOV   ecx,dword [v_Largeur] 
                              !Encore90Y: 
                                        !PUSH    ecx 
                                        !PUSH    eax 
                                        !MOV     ecx,dword [v_Longueur] 
                                        !Encore90X: 
                                                  !MOV    edx,dword[ebx] 
                                                  !MOV    dword[eax],edx 
                                                  !ADD     ebx,4 
                                                  !SUB     eax,dword [v_Largeur4] 
                                                  !DEC     ecx 
                                        !JNZ Encore90X 
                                        !POP eax 
                                        !ADD eax,4 
                                        !POP ecx 
                                        !DEC ecx 
                              !JNZ Encore90Y 
                              ;/ 
                    Next 
                    Temps2 = ElapsedMilliseconds() 
                    For t = 1 To #NbTest 
                              ;/ 
                              Temp1 = Longueur - 1 
                              ; Pour chaque point de l'image 
                              For n = 0 To Largeur - 1 
                                        For nn = 0 To Temp1 
                                                  PokeL(Mem2 + (n + (Temp1 - nn) * Largeur) * 4, PeekL(Mem + (nn + n * Longueur) * 4)) ; On fait une rotation de 90° 
                                                  ; Le * 4 vient du fait qu'on manipule des long 
                                        Next 
                              Next 
                              ;/ 
                    Next 
                    Temps3 = ElapsedMilliseconds() 
          EndIf 
EndIf 
MessageRequester("Vitesse", "Temps ASM : " + StrF((Temps2 - Temps1)/#NbTest) + " ms" + Chr(10) + "Temps PureBasic  : " + StrF((Temps3 - Temps2)/#NbTest) + " ms",#PB_MessageRequester_Ok) 
bien qu'il y ait un petit avantage pour l'ASM, c'est vrai qu'il passe inaperçus à côté des fonctions GetDIBits SetDIBits. Mais je ne pense pas qu'on puisse accéder directement à la mémoire, Windows la protège, seules les APIs le peuvent, c'est pour cela qu'elles sont aussi lente, c'est parce qu'elles doivent montrer leurs papiers à la douane :mrgreen:

Publié : dim. 13/févr./2005 12:54
par Anonyme2
Je ne suis pas sur que l'on puisse optimiser beaucoup si on manipule des nombres flottants (tu dois surement les utiliser dans tes calculs d'angles), car les calculs avec les nombres flottants consomment beaucoup de temps.

Je crois que l'optimisation devrait d'abord passer par une recherche d'un meilleur algorithme si c'est possible.

Si on peut utiliser des tables avec des valeurs précalculées, il faut le faire, ça accelère souvent le résultat (limitation des calculs).

Lors de la compilation, sélectionne l'option ALL CPU, PB va intégrer un test sur le type de CPU et ajouter des routines optimisées (mais là je ne sais pas sur quelles fonctions portent les optimisations)

Publié : dim. 13/févr./2005 13:16
par Anonyme2
J'ai une erreur à la ligne 110 avec le debuggeur
Plot is outside the drawing area

J'ai PB 3.92 beta2 et toutes les mises à jour des libs du site PureBasic beta

Publié : dim. 13/févr./2005 15:27
par Le Soldat Inconnu
pas normal :? ça marche très bien chez moi

Code : Tout sélectionner

ImageOrigine = CreateImage(0, 1000, 1000) 
StartDrawing(ImageOutput()) 
  For n = 0 To 999 
    For nn = 0 To 999 
      Plot(n, nn, Random($FFFFFF)) 
    Next 
  Next 
StopDrawing() 
regarde, c'est pas possible d'avoir un plot en dehors de l'image
l'image fait 1000*1000 et je vais de 0 à 999 avec un For
Il y a un blème avec les Beta

Publié : dim. 13/févr./2005 15:45
par Le Soldat Inconnu
je viens de penser à un truc :

on a la fonction PlgBlt_( qui visiblement permet de faire des rotations mais compatible uniquement sur 2000 et XP

mais rien n'empêche de faire un condition pour choisir cette fonction si l'OS est > à win 2000, et d'utiliser mon code sinon.

C'est compatible tout OS et ça ira peut-être plus vite sur XP et 2000 :)

la description de l'API en question est la :
http://msdn.microsoft.com/library/defau ... s_0qk3.asp




Sinon, pour la rotation avec un angle quelconque + lissage, la, il n'y a pas d'API, ou alors je suis bigleux :lol:

Voici mon code :
4.3 s sur mon 900mhz pour faire une rotation d'une image de 1000*1000

Il n'y a rien d'optimiser, il est brut de fonderie

Code : Tout sélectionner

ProcedureDLL.l RotateImageEx2(ImageID, Angle.f) ; Rotation d'une image d'un angle en °
  Protected bmi.BITMAPINFO, bmi2.BITMAPINFO, Hdc.l, NewImageID, Mem, n, nn, bm.BITMAP, Temp1, Temp2
  
  Angle = Angle * #Pi / 180 ; On convertit en radian
  
  GetObject_(ImageID, SizeOf(BITMAP), @bm.BITMAP)
  
  bmi\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
  bmi\bmiHeader\biWidth = bm\bmWidth
  bmi\bmiHeader\biHeight = bm\bmHeight
  bmi\bmiHeader\biPlanes = 1
  bmi\bmiHeader\biBitCount = 32
  bmi\bmiHeader\biCompression = #BI_RGB
  
  bmi2\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
  bmi2\bmiHeader\biWidth = Int(bm\bmWidth * Abs(Cos(Angle)) + bm\bmHeight * Abs(Sin(Angle)) + 0.5)
  bmi2\bmiHeader\biHeight = Int(bm\bmHeight * Abs(Cos(Angle)) + bm\bmWidth * Abs(Sin(Angle)) + 0.5)
  bmi2\bmiHeader\biPlanes = 1
  bmi2\bmiHeader\biBitCount = 32
  bmi2\bmiHeader\biCompression = #BI_RGB
  
  Mem = AllocateMemory(bm\bmWidth * bm\bmHeight * 4)
  If Mem
    Mem2 = AllocateMemory(bmi2\bmiHeader\biWidth * bmi2\bmiHeader\biHeight * 4)
    If Mem2
      
      Hdc = CreateCompatibleDC_(GetDC_(ImageID))
      If Hdc
        GetDIBits_(Hdc, ImageID, 0, bm\bmHeight, Mem, @bmi, #DIB_RGB_COLORS) ; on envoie la liste dans l'image
        ReleaseDC_(0, Hdc)
      EndIf
      
      CX1 = (bm\bmWidth - 1) * 100 / 2
      CY1 = (bm\bmHeight - 1) * 100 / 2
      CX2 = (bmi2\bmiHeader\biWidth - 1) * 100 / 2
      CY2 = (bmi2\bmiHeader\biHeight - 1) * 100 / 2
      For n = 0 To bmi2\bmiHeader\biWidth - 1
        For nn = 0 To bmi2\bmiHeader\biHeight - 1
          x2 = n * 100 - CX2
          y2 = nn * 100 - CY2
          x1.f = Int(CX1 + x2 * Cos(Angle) - y2 * Sin(Angle)) / 100
          y1.f = Int(CY1 + x2 * Sin(Angle) + y2 * Cos(Angle)) / 100
          
          If x1 < 0 : PasX = -1 : Else : PasX = 1 : EndIf
          If y1 < 0 : PasY = -1 : Else : PasY = 1 : EndIf
          
          If Int(x1) < 0 Or Int(x1) > bm\bmWidth - 1 Or Int(y1) < 0 Or Int(y1) > bm\bmHeight - 1
            c00 = 0
          Else
            c00 = PeekL(Mem + (Int(x1) + Int(y1) * bm\bmWidth) * 4)
          EndIf
          If Int(x1 + PasX) < 0 Or Int(x1 + PasX) > bm\bmWidth - 1 Or Int(y1) < 0 Or Int(y1) > bm\bmHeight - 1
            c10 = 0
          Else
            c10 = PeekL(Mem + (Int(x1 + PasX) + Int(y1) * bm\bmWidth) * 4)
          EndIf
          If Int(x1) < 0 Or Int(x1) > bm\bmWidth - 1 Or Int(y1 + PasY) < 0 Or Int(y1 + PasY) > bm\bmHeight - 1
            c01 = 0
          Else
            c01 = PeekL(Mem + (Int(x1) + Int(y1 + PasY) * bm\bmWidth) * 4)
          EndIf
          If Int(x1 + PasX) < 0 Or Int(x1 + PasX) > bm\bmWidth - 1 Or Int(y1 + PasY) < 0 Or Int(y1 + PasY) > bm\bmHeight - 1
            c11 = 0
          Else
            c11 = PeekL(Mem + (Int(x1 + PasX) + Int(y1 + PasY) * bm\bmWidth) * 4)
          EndIf
          fx.f = Abs(x1 - Int(x1))
          fy.f = Abs(y1 - Int(y1))
          f00.f = (1 - fx) * (1 - fy)
          f01.f = (1 - fx) * fy
          f10.f = fx * (1 - fy)
          f11.f = fx * fy
          r = Int(Red(c00) * f00 + Red(c10) * f10 + Red(c01) * f01 + Red(c11) * f11)
          g = Int(Green(c00) * f00 + Green(c10) * f10 + Green(c01) * f01 + Green(c11) * f11)
          b = Int(Blue(c00) * f00 + Blue(c10) * f10 + Blue(c01) * f01 + Blue(c11) * f11)
          
          PokeL(Mem2 + (n + nn * bmi2\bmiHeader\biWidth) * 4, RGB(r, g, b))
          
        Next
      Next
      
      ; On crée la nouvelle image
      NewImageID = CreateImage(#PB_Any, bmi2\bmiHeader\biWidth, bmi2\bmiHeader\biHeight)
      Hdc = CreateCompatibleDC_(GetDC_(ImageID()))
      If Hdc
        SetDIBits_(Hdc, ImageID(), 0, bmi2\bmiHeader\biHeight, Mem2, @bmi2, #DIB_RGB_COLORS) ; on envoie la liste dans l'image
        ReleaseDC_(0, Hdc)
      EndIf
      
      FreeMemory(Mem2)
    EndIf
    FreeMemory(Mem)
  EndIf
  
  ProcedureReturn NewImageID
EndProcedure



;-----------------------------------------
;- Test de rapidité

ImageOrigine = CreateImage(0, 1000, 1000)
StartDrawing(ImageOutput())
  For n = 0 To 999
    For nn = 0 To 999
      Plot(n, nn, Random($FFFFFF))
    Next
  Next
StopDrawing()
Dim Liste(ImageWidth() - 1, ImageHeight() - 1)

#NbTest = 2

Temps1 = ElapsedMilliseconds()

For n = 1 To #NbTest
  ImageModifiee = RotateImageEx2(ImageOrigine, 30)
Next

Temps2 = ElapsedMilliseconds()

Vitesse = (Temps2 - Temps1) / #NbTest
NbPixel = ImageHeight() * ImageWidth()

MessageRequester("Temps", Str(Vitesse) + " ms" + Chr(10) + "Image de " + Str(ImageWidth()) + " * " + Str(ImageHeight()) + " pixels" + Chr(10) + "Nb pixels traités = " + Str(NbPixel), 0)


;-----------------------------------------
;- Test  d'affichage d'image avec rotation
; On dessine une image
ImageNormale = CreateImage(#PB_Any, 80, 100)
StartDrawing(ImageOutput())
  Box(0, 0, 80, 100, $6F6F6F)
  Box(5, 5, 35, 45, $FF)
  Box(40, 5, 35, 45, $FF00)
  Box(5, 50, 35, 45, $FF0000)
  Box(40, 50, 35, 45, $FFFFFF)
StopDrawing()

ImageRotation = RotateImageEx2(UseImage(ImageNormale), 30)

; Création de la fenêtre et de la GadgetList
If OpenWindow(0, 0, 0, 250, 300, #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget, "Effect - Rotation d'image") = 0 Or CreateGadgetList(WindowID()) = 0
  End
EndIf

TextGadget(#PB_Any, 10, 10, 100, 15, "Image normale")
ImageGadget(#PB_Any, 10, 25, 0, 0, UseImage(ImageNormale))

TextGadget(#PB_Any, 10, 135, 100, 15, "Rotation de 30")
ImageGadget(#PB_Any, 10, 150, 0, 0, UseImage(ImageRotation))

Repeat
  Event = WaitWindowEvent()
  
Until Event = #PB_EventCloseWindow

End

Publié : lun. 14/févr./2005 19:50
par Le Soldat Inconnu
Bon, optimisation du code pour faire la rotation d'image avec un angle quelconque.

Sur mon 900mhz, la rotation d'une image de 1000*1000 d'un angle de 30° met 1.3s au lieu 4.5s auparavant :D

J'ai mis à jour la lib sur mon site pour les intéressés

Publié : lun. 14/févr./2005 20:25
par erix14
Moi aussi j'ai optimisé le code PureBasic avant de m'attaquer à l'optimisation en assembleur. Pour pouvoir comparer équitablement les deux versions.( Le code ASM dans la procédure n'est là que à cause des nombres signés, j'ai juste remplacé les MOVSX )

Code : Tout sélectionner

#Pi = 3.1415926
ProcedureDLL.l RotateImageEx2(ImageID, Angle.f) ; Rotation d'une image d'un angle en ° 
          Protected bmi.BITMAPINFO, bmi2.BITMAPINFO, hDC.l, NewImageID, Mem, n, nn, bm.BITMAP, Temp1, Temp2 
          
          Angle = Angle * #Pi / 180 ; On convertit en radian 
          CosAngle.f = Cos(Angle)
          SinAngle.f = Sin(Angle)
          
          GetObject_(ImageID, SizeOf(BITMAP), @bm.BITMAP) 
          
          bmi\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER) 
          bmi\bmiHeader\biWidth = bm\bmWidth 
          bmi\bmiHeader\biHeight = bm\bmHeight 
          bmi\bmiHeader\biPlanes = 1 
          bmi\bmiHeader\biBitCount = 32 
          bmi\bmiHeader\biCompression = #BI_RGB 
          
          bmi2\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER) 
          bmi2\bmiHeader\biWidth = Int(bm\bmWidth * Abs(CosAngle) + bm\bmHeight * Abs(SinAngle) + 0.5) 
          bmi2\bmiHeader\biHeight = Int(bm\bmHeight * Abs(CosAngle) + bm\bmWidth * Abs(SinAngle) + 0.5) 
          bmi2\bmiHeader\biPlanes = 1 
          bmi2\bmiHeader\biBitCount = 32 
          bmi2\bmiHeader\biCompression = #BI_RGB 
          
          Mem = AllocateMemory(bm\bmWidth * bm\bmHeight * 4) 
          If Mem 
                    Mem2 = AllocateMemory(bmi2\bmiHeader\biWidth * bmi2\bmiHeader\biHeight * 4) 
                    If Mem2 
                              
                              hDC = CreateCompatibleDC_(GetDC_(ImageID)) 
                              If hDC 
                                        GetDIBits_(hDC, ImageID, 0, bm\bmHeight, Mem, @bmi, #DIB_RGB_COLORS) ; on envoie la liste dans l'image 
                                        ReleaseDC_(0, hDC) 
                              EndIf 
                              
                              CX1 = (bm\bmWidth - 1) * 100 / 2 
                              CY1 = (bm\bmHeight - 1) * 100 / 2 
                              CX2 = (bmi2\bmiHeader\biWidth - 1) * 100 / 2 
                              CY2 = (bmi2\bmiHeader\biHeight - 1) * 100 / 2 
                              
                              Largeur = bm\bmHeight - 1 
                              longueur = bm\bmWidth - 1
                              
                              CouleurNoir = 0
                              
                              *pMem2.RGBQUAD = Mem2
                              For nn = 0 To bmi2\bmiHeader\biHeight - 1 
                                        y2 = nn * 100 - CY2
                                        CX1y2Sin = CX1  - y2 * SinAngle
                                        CY1y2Cos = CY1 + y2 * CosAngle
                                        For n = 0 To bmi2\bmiHeader\biWidth - 1 
                                                  x2 = n * 100 - CX2 
                                                  x1.f = Int(x2 * CosAngle + CX1y2Sin) / 100 
                                                  y1.f = Int(x2 * SinAngle + CY1y2Cos) / 100 
                                                  
                                                  IntX1 = Int(x1)
                                                  Inty1 = Int(y1)
                                                  
                                                  If x1 < 0 : PasX = IntX1 - 1 : Else : PasX = IntX1 + 1 : EndIf 
                                                  If y1 < 0 : PasY = Inty1 - 1 : Else : PasY = Inty1 + 1 : EndIf 
                                                  
                                                  If IntX1 < 0 Or IntX1 > longueur Or Inty1 < 0 Or Inty1 > Largeur
                                                            *c00.RGBQUAD = @CouleurNoir
                                                  Else 
                                                            *c00 = Mem + (IntX1 + Inty1 * bm\bmWidth) * 4
                                                  EndIf 
                                                  If PasX < 0 Or PasX > longueur Or Inty1 < 0 Or Inty1 > Largeur
                                                            *c10.RGBQUAD = @CouleurNoir
                                                  Else 
                                                            *c10 = Mem + (PasX + Inty1 * bm\bmWidth) * 4
                                                  EndIf 
                                                  If IntX1 < 0 Or IntX1 > longueur Or PasY < 0 Or PasY > Largeur
                                                            *c01.RGBQUAD = @CouleurNoir 
                                                  Else 
                                                            *c01 = Mem + (IntX1 + PasY * bm\bmWidth) * 4
                                                  EndIf 
                                                  If PasX < 0 Or PasX > longueur Or PasY < 0 Or PasY > Largeur
                                                            *c11.RGBQUAD = @Couleur 
                                                  Else 
                                                            *c11 = Mem + (PasX + PasY * bm\bmWidth) * 4
                                                  EndIf 
                                                  
                                                  fx.f = Abs(x1 - IntX1) 
                                                  fy.f = Abs(y1 - Inty1) 
                                                  f00.f = (1 - fx) * (1 - fy) 
                                                  f01.f = (1 - fx) * fy 
                                                  f10.f = fx * (1 - fy) 
                                                  f11.f = fx * fy 
                                                  
                                                  !XOR eax,eax
                                                  ; *pMem2\rgbRed = Int(*c00\rgbRed * f00 + *c10\rgbRed * f10 + *c01\rgbRed * f01 + *c11\rgbRed * f11) 
                                                  !MOV    ebp,dword [esp+232]
                                                  !MOV  al,byte [ebp+2]
                                                  !MOV    dword [esp-4],eax
                                                  !FILD   dword [esp-4]
                                                  !FMUL   dword [esp+260]
                                                  !MOV    ebp,dword [esp+236]
                                                  !MOV  al,byte [ebp+2]
                                                  !MOV    dword [esp-4],eax
                                                  !FILD   dword [esp-4]
                                                  !FMUL   dword [esp+268]
                                                  !FADDP  ST1,ST0
                                                  !MOV    ebp,dword [esp+240]
                                                  !MOV  al,byte [ebp+2]
                                                  !MOV    dword [esp-4],eax
                                                  !FILD   dword [esp-4]
                                                  !FMUL   dword [esp+264]
                                                  !FADDP  ST1,ST0
                                                  !MOV    ebp,dword [esp+244]
                                                  !MOV  al,byte [ebp+2]
                                                  !MOV    dword [esp-4],eax
                                                  !FILD   dword [esp-4]
                                                  !FMUL   dword [esp+272]
                                                  !FADDP  ST1,ST0
                                                  !SUB    esp,4
                                                  !FSTP   dword [esp]
                                                  !CALL  _PB_Int@4
                                                  !MOV    ebp,dword [esp+192-4]
                                                  !MOV    byte [ebp+2],al
                                                  ; *pMem2\rgbGreen = Int(*c00\rgbGreen * f00 + *c10\rgbGreen * f10 + *c01\rgbGreen * f01 + *c11\rgbGreen * f11) 
                                                  !MOV    ebp,dword [esp+232]
                                                  !MOV  al,byte [ebp+1]
                                                  !MOV    dword [esp-4],eax
                                                  !FILD   dword [esp-4]
                                                  !FMUL   dword [esp+260]
                                                  !MOV    ebp,dword [esp+236]
                                                  !MOV  al,byte [ebp+1]
                                                  !MOV    dword [esp-4],eax
                                                  !FILD   dword [esp-4]
                                                  !FMUL   dword [esp+268]
                                                  !FADDP  ST1,ST0
                                                  !MOV    ebp,dword [esp+240]
                                                  !MOV  al,byte [ebp+1]
                                                  !MOV    dword [esp-4],eax
                                                  !FILD   dword [esp-4]
                                                  !FMUL   dword [esp+264]
                                                  !FADDP  ST1,ST0
                                                  !MOV    ebp,dword [esp+244]
                                                  !MOV  al,byte [ebp+1]
                                                  !MOV    dword [esp-4],eax
                                                  !FILD   dword [esp-4]
                                                  !FMUL   dword [esp+272]
                                                  !FADDP  ST1,ST0
                                                  !SUB    esp,4
                                                  !FSTP   dword [esp]
                                                  !CALL  _PB_Int@4
                                                  !MOV    ebp,dword [esp+192-4]
                                                  !MOV    byte [ebp+1],al
                                                  ; *pMem2\rgbBlue = Int(*c00\rgbBlue * f00 + *c10\rgbBlue * f10 + *c01\rgbBlue * f01 + *c11\rgbBlue * f11) 
                                                  !MOV    ebp,dword [esp+232]
                                                  !MOV  al,byte [ebp]
                                                  !MOV    dword [esp-4],eax
                                                  !FILD   dword [esp-4]
                                                  !FMUL   dword [esp+260]
                                                  !MOV    ebp,dword [esp+236]
                                                  !MOV  al,byte [ebp]
                                                  !MOV    dword [esp-4],eax
                                                  !FILD   dword [esp-4]
                                                  !FMUL   dword [esp+268]
                                                  !FADDP  ST1,ST0
                                                  !MOV    ebp,dword [esp+240]
                                                  !MOV  al,byte [ebp]
                                                  !MOV    dword [esp-4],eax
                                                  !FILD   dword [esp-4]
                                                  !FMUL   dword [esp+264]
                                                  !FADDP  ST1,ST0
                                                  !MOV    ebp,dword [esp+244]
                                                  !MOV  al,byte [ebp]
                                                  !MOV    dword [esp-4],eax
                                                  !FILD   dword [esp-4]
                                                  !FMUL   dword [esp+272]
                                                  !FADDP  ST1,ST0
                                                  !SUB    esp,4
                                                  !FSTP   dword [esp]
                                                  !CALL  _PB_Int@4
                                                  !MOV    ebp,dword [esp+192-4]
                                                  !MOV    byte [ebp],al
                                                  
                                                  *pMem2 + 4
                                        Next 
                              Next 
                              
                              ; On crée la nouvelle image 
                              NewImageID = CreateImage(#PB_Any, bmi2\bmiHeader\biWidth, bmi2\bmiHeader\biHeight) 
                              hDC = CreateCompatibleDC_(GetDC_(ImageID())) 
                              If hDC 
                                        SetDIBits_(hDC, ImageID(), 0, bmi2\bmiHeader\biHeight, Mem2, @bmi2, #DIB_RGB_COLORS) ; on envoie la liste dans l'image 
                                        ReleaseDC_(0, hDC) 
                              EndIf 
                              
                              FreeMemory(Mem2) 
                    EndIf 
                    FreeMemory(Mem) 
          EndIf 
          
          ProcedureReturn NewImageID 
EndProcedure 



;----------------------------------------- 
;- Test de rapidité 

ImageOrigine = CreateImage(0, 1000, 1000) 
StartDrawing(ImageOutput()) 
For n = 0 To 999 
          For nn = 0 To 999 
                    Plot(n, nn, Random($FFFFFF)) 
          Next 
Next 
StopDrawing() 
Dim Liste(ImageWidth() - 1, ImageHeight() - 1) 

#NbTest = 2 

Temps1 = ElapsedMilliseconds() 

For n = 1 To #NbTest 
          ImageModifiee = RotateImageEx2(ImageOrigine, 30) 
Next 

Temps2 = ElapsedMilliseconds() 

Vitesse = (Temps2 - Temps1) / #NbTest 
NbPixel = ImageHeight() * ImageWidth() 

MessageRequester("Temps", Str(Vitesse) + " ms" + Chr(10) + "Image de " + Str(ImageWidth()) + " * " + Str(ImageHeight()) + " pixels" + Chr(10) + "Nb pixels traités = " + Str(NbPixel), 0) 


;----------------------------------------- 
;- Test  d'affichage d'image avec rotation 
; On dessine une image 
ImageNormale = CreateImage(#PB_Any, 80, 100) 
StartDrawing(ImageOutput()) 
Box(0, 0, 80, 100, $6F6F6F) 
Box(5, 5, 35, 45, $FF) 
Box(40, 5, 35, 45, $FF00) 
Box(5, 50, 35, 45, $FF0000) 
Box(40, 50, 35, 45, $FFFFFF) 
StopDrawing() 

ImageRotation = RotateImageEx2(UseImage(ImageNormale), 30) 

; Création de la fenêtre et de la GadgetList 
If OpenWindow(0, 0, 0, 250, 300, #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget, "Effect - Rotation d'image") = 0 Or CreateGadgetList(WindowID()) = 0 
          End 
EndIf 

TextGadget(#PB_Any, 10, 10, 100, 15, "Image normale") 
ImageGadget(#PB_Any, 10, 25, 0, 0, UseImage(ImageNormale)) 

TextGadget(#PB_Any, 10, 135, 100, 15, "Rotation de 30") 
ImageGadget(#PB_Any, 10, 150, 0, 0, UseImage(ImageRotation)) 

Repeat 
          Event = WaitWindowEvent() 
          
Until Event = #PB_EventCloseWindow 

End

Publié : lun. 14/févr./2005 20:42
par Le Soldat Inconnu
marrant, on a pratiquement fais la même chose :wink: sauf que tu as ajouté l'ASM et pour l'idée de la structure, pas bête :D

je regarde ;)

Publié : lun. 14/févr./2005 21:32
par Le Soldat Inconnu
Bon, j'ai continuer d'optimiser mon code

je suis à 1.2 seconde pour une image de 1000*1000 avec une rotation de 30°

Pour info Erix14, tu es à 1.5s chez moi. En faisant bénificer ton code de mes changements, tu es a 1.3 seconde. visiblement, les pointeurs sont pas une bonne solution



voici mon code :

Code : Tout sélectionner

#Pi.f = 3.14159265

ProcedureDLL.l RotateImageEx2(ImageID, Angle.f) ; Rotation d'une image d'un angle en °
  Protected bmi.BITMAPINFO, bmi2.BITMAPINFO, Hdc.l, NewImageID, Mem, n, nn, bm.BITMAP, Temp1, Temp2, Temp3.f, Temp4.f, Temp5.f, Temp6.f
  
  Angle = Angle * #Pi / 180 ; On convertit en radian
  
  CouleurFond = 0
  
  GetObject_(ImageID, SizeOf(BITMAP), @bm.BITMAP)
  
  bmi\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
  bmi\bmiHeader\biWidth = bm\bmWidth
  bmi\bmiHeader\biHeight = bm\bmHeight
  bmi\bmiHeader\biPlanes = 1
  bmi\bmiHeader\biBitCount = 32
  bmi\bmiHeader\biCompression = #BI_RGB
  
  bmi2\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
  bmi2\bmiHeader\biWidth = bm\bmWidth * Abs(Cos(Angle)) + bm\bmHeight * Abs(Sin(Angle))
  bmi2\bmiHeader\biHeight = bm\bmHeight * Abs(Cos(Angle)) + bm\bmWidth * Abs(Sin(Angle))
  bmi2\bmiHeader\biPlanes = 1
  bmi2\bmiHeader\biBitCount = 32
  bmi2\bmiHeader\biCompression = #BI_RGB
  
  Mem = AllocateMemory(bm\bmWidth * bm\bmHeight * 4)
  If Mem
    Mem2 = AllocateMemory(bmi2\bmiHeader\biWidth * bmi2\bmiHeader\biHeight * 4)
    If Mem2
      
      Hdc = CreateCompatibleDC_(GetDC_(ImageID))
      If Hdc
        GetDIBits_(Hdc, ImageID, 0, bm\bmHeight, Mem, @bmi, #DIB_RGB_COLORS) ; on envoie la liste dans l'image
        ReleaseDC_(0, Hdc)
      EndIf
      
      Temp1 = bm\bmWidth - 1
      Temp2 = bm\bmHeight - 1
      Temp3.f = Cos(Angle)
      Temp4.f = Sin(Angle)
      CX1 = Temp1 * 100 / 2
      CY1 = Temp2 * 100 / 2
      CX2 = (bmi2\bmiHeader\biWidth - 1) * 100 / 2
      CY2 = (bmi2\bmiHeader\biHeight - 1) * 100 / 2
      
      For n = 0 To bmi2\bmiHeader\biWidth - 1
        x1b.l = n * 100 - CX2
        Temp5 = CX1 + x1b * Temp3
        Temp6 = CY1 + x1b * Temp4
        For nn = 0 To bmi2\bmiHeader\biHeight - 1
          y1b.l = nn * 100 - CY2
          
          x1.f = (Temp5 - y1b * Temp4) / 100
          y1.f = (Temp6 + y1b * Temp3) / 100
          
          x2.l = x1
          y2.l = y1
          
          fx.f = Abs(x1 - x2)
          fy.f = Abs(y1 - y2)
          f00.f = (1 - fx) * (1 - fy)
          f01.f = (1 - fx) * fy
          f10.f = fx * (1 - fy)
          f11.f = fx * fy
          
          If x1 < x2 : x2b = x2 - 1 : Else : x2b = x2 + 1 : EndIf
          If y1 < y2 : y2b = y2 - 1 : Else : y2b = y2 + 1 : EndIf
          
          If x2 < 0 Or x2 > Temp1 
            c00 = 0
            c01 = 0
          Else
            If y2 < 0 Or y2 > Temp2
              c00 = 0
            Else
              c00 = PeekL(Mem + (x2 + y2 * bm\bmWidth) * 4)
            EndIf
            If y2b < 0 Or y2b > Temp2
              c01 = 0
            Else
              c01 = PeekL(Mem + (x2 + y2b * bm\bmWidth) * 4)
            EndIf
          EndIf
          If x2b < 0 Or x2b > Temp1
            c10 = 0
            c11 = 0
          Else
            If y2 < 0 Or y2 > Temp2
              c10 = 0
            Else
              c10 = PeekL(Mem + (x2b + y2 * bm\bmWidth) * 4)
            EndIf
            If  y2b < 0 Or y2b > Temp2
              c11 = 0
            Else
              c11 = PeekL(Mem + (x2b + y2b * bm\bmWidth) * 4)
            EndIf
          EndIf
          
          r = Red(c00) * f00 + Red(c10) * f10 + Red(c01) * f01 + Red(c11) * f11
          g = Green(c00) * f00 + Green(c10) * f10 + Green(c01) * f01 + Green(c11) * f11
          b = Blue(c00) * f00 + Blue(c10) * f10 + Blue(c01) * f01 + Blue(c11) * f11
          
          PokeL(Mem2 + (n + nn * bmi2\bmiHeader\biWidth) * 4, RGB(r, g, b))
          
        Next
      Next
      
      ; On crée la nouvelle image
      NewImageID = CreateImage(#PB_Any, bmi2\bmiHeader\biWidth, bmi2\bmiHeader\biHeight)
      Hdc = CreateCompatibleDC_(GetDC_(ImageID()))
      If Hdc
        SetDIBits_(Hdc, ImageID(), 0, bmi2\bmiHeader\biHeight, Mem2, @bmi2, #DIB_RGB_COLORS) ; on envoie la liste dans l'image
        ReleaseDC_(0, Hdc)
      EndIf
      
      FreeMemory(Mem2)
    EndIf
    FreeMemory(Mem)
  EndIf
  
  ProcedureReturn NewImageID
EndProcedure


;-----------------------------------------
;- Test de rapidité

ImageOrigine = CreateImage(0, 1000, 1000)
StartDrawing(ImageOutput())
  For n = 0 To 999
    For nn = 0 To 999
      Plot(n, nn, Random($FFFFFF))
    Next
  Next
StopDrawing()
Dim Liste(ImageWidth() - 1, ImageHeight() - 1)

#NbTest = 2

Temps1 = ElapsedMilliseconds()

For n = 1 To #NbTest
  ImageModifiee = RotateImageEx2(ImageOrigine, 30)
Next

Temps2 = ElapsedMilliseconds()

Vitesse = (Temps2 - Temps1) / #NbTest
NbPixel = ImageHeight() * ImageWidth()

MessageRequester("Temps", Str(Vitesse) + " ms" + Chr(10) + "Image de " + Str(ImageWidth()) + " * " + Str(ImageHeight()) + " pixels" + Chr(10) + "Nb pixels traités = " + Str(NbPixel), 0)


;-----------------------------------------
;- Test  d'affichage d'image avec rotation
; On dessine une image
ImageNormale = CreateImage(#PB_Any, 80, 100)
StartDrawing(ImageOutput())
  Box(0, 0, 80, 100, $6F6F6F)
  Box(5, 5, 35, 45, $FF)
  Box(40, 5, 35, 45, $FF00)
  Box(5, 50, 35, 45, $FF0000)
  Box(40, 50, 35, 45, $FFFFFF)
StopDrawing()

ImageRotation = RotateImageEx2(UseImage(ImageNormale), 30)

; Création de la fenêtre et de la GadgetList
If OpenWindow(0, 0, 0, 250, 300, #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget, "Effect - Rotation d'image") = 0 Or CreateGadgetList(WindowID()) = 0
  End
EndIf

TextGadget(#PB_Any, 10, 10, 100, 15, "Image normale")
ImageGadget(#PB_Any, 10, 25, 0, 0, UseImage(ImageNormale))

TextGadget(#PB_Any, 10, 135, 100, 15, "Rotation de 30")
ImageGadget(#PB_Any, 10, 150, 0, 0, UseImage(ImageRotation))

Repeat
  Event = WaitWindowEvent()
  
Until Event = #PB_EventCloseWindow

End

Publié : lun. 14/févr./2005 22:44
par djes
On peut jouer? :D