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"...
Code:
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