Publié : sam. 12/févr./2005 20:44
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 ?

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 ?
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
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
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)
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()
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
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
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