Oui, je veux bien le faireDu 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 ?
Librairie Effect
-
Le Soldat Inconnu
- Messages : 4312
- Inscription : mer. 28/janv./2004 20:58
- Localisation : Clermont ferrand OU Olsztyn
- Contact :
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
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
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
EndJe ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?
[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Voilà c'est fait
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"...
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-
Le Soldat Inconnu
- Messages : 4312
- Inscription : mer. 28/janv./2004 20:58
- Localisation : Clermont ferrand OU Olsztyn
- Contact :
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
240 contre 250.
c'est pas flaggrant
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
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?
[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
J'ai isolé les boucles des traitements graphiques pour voir les temps :
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 
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)
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)
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)
-
Le Soldat Inconnu
- Messages : 4312
- Inscription : mer. 28/janv./2004 20:58
- Localisation : Clermont ferrand OU Olsztyn
- Contact :
pas normal
ça marche très bien chez moi
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
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() l'image fait 1000*1000 et je vais de 0 à 999 avec un For
Il y a un blème avec les Beta
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?
[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
-
Le Soldat Inconnu
- Messages : 4312
- Inscription : mer. 28/janv./2004 20:58
- Localisation : Clermont ferrand OU Olsztyn
- Contact :
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
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
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
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
EndJe ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?
[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
-
Le Soldat Inconnu
- Messages : 4312
- Inscription : mer. 28/janv./2004 20:58
- Localisation : Clermont ferrand OU Olsztyn
- Contact :
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
J'ai mis à jour la lib sur mon site pour les intéressés
Sur mon 900mhz, la rotation d'une image de 1000*1000 d'un angle de 30° met 1.3s au lieu 4.5s auparavant
J'ai mis à jour la lib sur mon site pour les intéressés
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?
[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
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-
Le Soldat Inconnu
- Messages : 4312
- Inscription : mer. 28/janv./2004 20:58
- Localisation : Clermont ferrand OU Olsztyn
- Contact :
-
Le Soldat Inconnu
- Messages : 4312
- Inscription : mer. 28/janv./2004 20:58
- Localisation : Clermont ferrand OU Olsztyn
- Contact :
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 :
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
EndJe ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?
[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]