tu lance le code, tu regarde le temps obtenu, tu bidouille et si tu va plus vite, tu as gagné

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
DefType.f x1,y1
DefType.l x1b,y1b,fxl,fyl,f00l,f01l,f10l,f11l
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) * 512 / 2
CY1 = (bm\bmHeight - 1) * 512 / 2
CX2 = (bmi2\bmiHeader\biWidth - 1) * 512 / 2
CY2 = (bmi2\bmiHeader\biHeight - 1) * 512 / 2
;un seul Dim est surement plus rapide que 2
If bmi2\bmiHeader\biWidth>bmi2\bmiHeader\biHeight
Dim tabxy2.f(bmi2\bmiHeader\biWidth,4)
Else
Dim tabxy2.f(bmi2\bmiHeader\biHeight,4)
EndIf
x2.f=-CX2
sin.f=Sin(angle)
cos.f=Cos(angle)
For i = 0 To bmi2\bmiHeader\biWidth - 1
tabxy2(i,0)=CX1+x2*cos
tabxy2(i,1)=CY1+x2*sin
x2+512.0
Next
y2.f=-CY2
For i = 0 To bmi2\bmiHeader\biHeight - 1
tabxy2(i,2)=y2*sin
tabxy2(i,3)=y2*cos
y2+512.0
Next
i.l=mem2
w.l=bmi2\bmiHeader\biWidth*4
maxx.l=bm\bmWidth*4
maxy.l=mem+(bm\bmWidth-1 + (bm\bmHeight-1) * bm\bmWidth) * 4
For o.l = 0 To bmi2\bmiHeader\biWidth - 1
u.l=i
i+4
x2cos.f=tabxy2(o,0)
x2sin.f=tabxy2(o,1)
For oo.l = 0 To bmi2\bmiHeader\biHeight - 1
x1b = x2cos - tabxy2(oo,2)
y1b = x2sin + tabxy2(oo,3)
x1=x1b/512.0
y1=y1b/512.0
If x1b<0 : x1b=-x1b:EndIf
If y1b<0 : y1b=-y1b:EndIf
fxl = x1b & $000001FF
fyl = y1b & $000001FF
f00l = (511- fxl) * (511-fyl)
f01l = (511- fxl) * fyl
f10l = fxl * (511 - fyl)
f11l = fxl * fyl
f00l>>9
f01l>>9
f10l>>9
f11l>>9
If x1 < 0 : PasX.l = -4 : Else : PasX = 4 : EndIf
If y1 < 0 : PasY.l = -maxx : Else : PasY = maxx : EndIf
xx1.l=Int(x1)
xx1*4
xx2=xx1+PasX
yy1.l=Int(y1)
yy1*maxx
pos1.l=mem+xx1 + yy1
pos2.l=pos1 + PasX
pos3.l=pos1 + PasY
pos4.l=pos3 + PasX
If xx1<0 Or xx1>maxx
c00=0
c01=0
Else
If pos1>=mem And pos1<=maxy
c00 = PeekL(pos1)
Else
c00=0
EndIf
If pos3>=mem And pos3<=maxy
c01 = PeekL(pos3)
Else
c01=0
EndIf
EndIf
If xx2<0 Or xx2>maxx
c10=0
c11=0
Else
If pos2>=mem And pos2<=maxy
c10 = PeekL(pos2)
Else
c10=0
EndIf
If pos4>=mem And pos4<=maxy
c11 = PeekL(pos4)
Else
c11=0
EndIf
EndIf
r.l = (Red(c00) * f00l)>>9 + (Red(c10) * f10l)>>9 + (Red(c01) * f01l)>>9 + (Red(c11) * f11l)>>9
g.l = (Green(c00) * f00l)>>9 + (Green(c10) * f10l)>>9 + (Green(c01) * f01l)>>9 + (Green(c11) * f11l)>>9
b.l = (Blue(c00) * f00l)>>9 + (Blue(c10) * f10l)>>9 + (Blue(c01) * f01l)>>9 + (Blue(c11) * f11l)>>9
PokeL(u , RGB(r, g, b))
u+w
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
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
Angle = Angle * #Pi / 180 ; On convertit en radian
cos.f = Cos(Angle)
sin.f = Sin(Angle)
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) + bm\bmHeight * Abs(sin)
bmi2\bmiHeader\biHeight = bm\bmHeight * Abs(cos) + bm\bmWidth * Abs(sin)
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
CY1 = bm\bmHeight - 1
CX2 = bmi2\bmiHeader\biWidth - 1
CY2 = bmi2\bmiHeader\biHeight - 1
For n = 0 To CX2
x1b.l = (n << 1) - CX2
Temp1.f = CX1 + x1b * cos
Temp2.f = CY1 + x1b * sin
For nn = 0 To CY2
y1b.l = (nn << 1) - CY2
x1.f = (Temp1 - y1b * sin) / 2
y1.f = (Temp2 + y1b * cos) / 2
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 > CX1
c00 = 0
c01 = 0
Else
If y2 < 0 Or y2 > CY1
c00 = 0
Else
c00 = PeekL(Mem + (x2 + y2 * bm\bmWidth) * 4)
EndIf
If y2b < 0 Or y2b > CY1
c01 = 0
Else
c01 = PeekL(Mem + (x2 + y2b * bm\bmWidth) * 4)
EndIf
EndIf
If x2b < 0 Or x2b > CX1
c10 = 0
c11 = 0
Else
If y2 < 0 Or y2 > CY1
c10 = 0
Else
c10 = PeekL(Mem + (x2b + y2 * bm\bmWidth) * 4)
EndIf
If y2b < 0 Or y2b > CY1
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 = 3
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
DefType.f x1,y1
DefType.l x1b,y1b,fxl,fyl,f00l,f01l,f10l,f11l
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) * 512 / 2
CY1 = (bm\bmHeight - 1) * 512 / 2
CX2 = (bmi2\bmiHeader\biWidth - 1) * 512 / 2
CY2 = (bmi2\bmiHeader\biHeight - 1) * 512 / 2
;un seul Dim est surement plus rapide que 2
If bmi2\bmiHeader\biWidth>bmi2\bmiHeader\biHeight
Dim tabxy2.l(bmi2\bmiHeader\biWidth,4)
Else
Dim tabxy2.l(bmi2\bmiHeader\biHeight,4)
EndIf
x2.f=-CX2
sin.f=Sin(angle)
cos.f=Cos(angle)
For i = 0 To bmi2\bmiHeader\biWidth - 1
tabxy2(i,0)=CX1+x2*cos
tabxy2(i,1)=CY1+x2*sin
x2+512.0
Next
y2.f=-CY2
For i = 0 To bmi2\bmiHeader\biHeight - 1
tabxy2(i,2)=y2*sin
tabxy2(i,3)=y2*cos
y2+512.0
Next
i.l=mem2
w.l=bmi2\bmiHeader\biWidth*4
tailleligne=bm\bmWidth * 4
maxx.l=(bm\bmWidth-1)*4
maxy.l=(bm\bmHeight-1) * tailleligne
For o.l = 0 To bmi2\bmiHeader\biWidth - 1
u.l=i
i+4
x2cos.l=tabxy2(o,0)
x2sin.l=tabxy2(o,1)
For oo.l = 0 To bmi2\bmiHeader\biHeight - 1
x1b = x2cos - tabxy2(oo,2)
y1b = x2sin + tabxy2(oo,3)
; If xx1<0 : xx1=-xx1:EndIf
If yy1<0 : yy1=-yy1:EndIf ;!!!!!!!!!
If xx1 < 0 : PasX.l = -4 : Else : PasX = 4 : EndIf
If yy1 < 0 : PasY.l = -tailleligne: Else : PasY = tailleligne: EndIf
xx1.l=x1b>>9
xx1*4
yy1.l=y1b>>9
yy1*tailleligne
xx2=xx1+PasX
yy2=yy1+PasY
fxl = x1b & $000001FF
fyl = y1b & $000001FF
f00l = (511- fxl) * (511-fyl)
f01l = (511- fxl) * fyl
f10l = fxl * (511 - fyl)
f11l = fxl * fyl
f00l>>9
f01l>>9
f10l>>9
f11l>>9
If xx1<0 Or xx1>maxx
c00=0
c01=0
Else
pos1.l=mem+xx1 + yy1
If yy1<0 Or yy1>maxy
c00 = 0
Else
c00 =PeekL(pos1)
EndIf
If yy2<0 Or yy2>maxy
c01 = 0
Else
c01 = PeekL(pos1+PasY)
EndIf
EndIf
If xx2<0 Or xx2>maxx
c10=0
c11=0
Else
pos1.l=mem+xx2 + yy1
If yy1<0 Or yy1>maxy
c10 = 0
Else
c10 = PeekL(pos1)
EndIf
If yy2<0 Or yy2>maxy
c11 = 0
Else
c11 = PeekL(pos1+PasY)
EndIf
EndIf
r.l = (Red(c00) * f00l)>>9 + (Red(c10) * f10l)>>9 + (Red(c01) * f01l)>>9 + (Red(c11) * f11l)>>9
g.l = (Green(c00) * f00l)>>9 + (Green(c10) * f10l)>>9 + (Green(c01) * f01l)>>9 + (Green(c11) * f11l)>>9
b.l = (Blue(c00) * f00l)>>9 + (Blue(c10) * f10l)>>9 + (Blue(c01) * f01l)>>9 + (Blue(c11) * f11l)>>9
PokeL(u , RGB(r, g, b))
u+w
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
DefType.f x1,y1
DefType.l x1b,y1b,fxl,fyl,f00l,f01l,f10l,f11l
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) * 512 / 2
CY1 = (bm\bmHeight - 1) * 512 / 2
CX2 = (bmi2\bmiHeader\biWidth - 1) * 512 / 2
CY2 = (bmi2\bmiHeader\biHeight - 1) * 512 / 2
;un seul Dim est surement plus rapide que 2
If bmi2\bmiHeader\biWidth>bmi2\bmiHeader\biHeight
Dim tabxy2.l(bmi2\bmiHeader\biWidth,4)
Else
Dim tabxy2.l(bmi2\bmiHeader\biHeight,4)
EndIf
x2.f=-CX2
sin.f=Sin(angle)
cos.f=Cos(angle)
For i = 0 To bmi2\bmiHeader\biWidth - 1
tabxy2(i,0)=CX1+x2*cos
tabxy2(i,1)=CY1+x2*sin
x2+512.0
Next
y2.f=-CY2
For i = 0 To bmi2\bmiHeader\biHeight - 1
tabxy2(i,2)=y2*sin
tabxy2(i,3)=y2*cos
y2+512.0
Next
i.l=mem2
w.l=bmi2\bmiHeader\biWidth*4
tailleligne=bm\bmWidth * 4
maxx.l=(bm\bmWidth-1)*4
maxy.l=(bm\bmHeight-1) * tailleligne
For o.l = 0 To bmi2\bmiHeader\biWidth - 1
u.l=i
i+4
x2cos.l=tabxy2(o,0)
x2sin.l=tabxy2(o,1)
For oo.l = 0 To bmi2\bmiHeader\biHeight - 1
x1b = x2cos - tabxy2(oo,2)
y1b = x2sin + tabxy2(oo,3)
; If xx1<0 : xx1=-xx1:EndIf
If yy1<0 : yy1=-yy1:EndIf ;!!!!!!!!!
If xx1 < 0 : PasX.l = -4 : Else : PasX = 4 : EndIf
If yy1 < 0 : PasY.l = -tailleligne: Else : PasY = tailleligne: EndIf
xx1.l=x1b>>9
xx1*4
yy1.l=y1b>>9
yy1*tailleligne
xx2=xx1+PasX
yy2=yy1+PasY
fxl = x1b & $000001FF
fyl = y1b & $000001FF
f00l = (511- fxl) * (511-fyl)
f01l = (511- fxl) * fyl
f10l = fxl * (511 - fyl)
f11l = fxl * fyl
f00l>>9
f01l>>9
f10l>>9
f11l>>9
If xx1<0 Or xx1>maxx
c00=0
c01=0
Else
pos1.l=mem+xx1 + yy1
If yy1<0 Or yy1>maxy
c00 = 0
Else
MOV eax,pos1
MOV eax,[eax]
MOV c00,eax
;c00 =PeekL(pos1)
EndIf
If yy2<0 Or yy2>maxy
c01 = 0
Else
MOV eax,pos1
ADD eax,PasY
MOV eax,[eax]
MOV c01,eax
;c01 = PeekL(pos1+PasY)
EndIf
EndIf
If xx2<0 Or xx2>maxx
c10=0
c11=0
Else
pos1.l=mem+xx2 + yy1
If yy1<0 Or yy1>maxy
c10 = 0
Else
MOV eax,pos1
MOV eax,[eax]
MOV c10,eax
;c10 = PeekL(pos1)
EndIf
If yy2<0 Or yy2>maxy
c11 = 0
Else
MOV eax,pos1
ADD eax,PasY
MOV eax,[eax]
MOV c11,eax
;c11 = PeekL(pos1+PasY)
EndIf
EndIf
; r.l = (Red(c00) * f00l)>>9 + (Red(c10) * f10l)>>9 + (Red(c01) * f01l)>>9 + (Red(c11) * f11l)>>9
;(Red(c00) * f00l)>>9
MOV eax,c00
AND eax,$FF
IMUL eax,f00l
;(Red(c10) * f10l)>>9
MOV ebx,c10
AND ebx,$FF
IMUL ebx,f10l
ADD eax,ebx
;(Red(c01) * f01l)>>9
MOV ebx,c01
AND ebx,$FF
IMUL ebx,f01l
ADD eax,ebx
;(Red(c11) * f11l)>>9
MOV ebx,c11
AND ebx,$FF
IMUL ebx,f11l
ADD eax,ebx
SAR eax,9
AND eax,$000000FF
MOV ecx,eax
; g.l = (Green(c00) * f00l)>>9 + (Green(c10) * f10l)>>9 + (Green(c01) * f01l)>>9 + (Green(c11) * f11l)>>9
;(Green(c00) * f00l)>>9
MOV eax,c00
AND eax,$00FF00
IMUL eax,f00l
;(Green(c10) * f10l)>>9
MOV ebx,c10
AND ebx,$00FF00
IMUL ebx,f10l
ADD eax,ebx
;(Green(c01) * f01l)>>9
MOV ebx,c01
AND ebx,$00FF00
IMUL ebx,f01l
ADD eax,ebx
;(Green(c11) * f11l)>>9
MOV ebx,c11
AND ebx,$00FF00
IMUL ebx,f11l
ADD eax,ebx
SAR eax,9
AND eax,$0000FF00
OR ecx,eax
; b.l = (Blue(c00) * f00l)>>9 + (Blue(c10) * f10l)>>9 + (Blue(c01) * f01l)>>9 + (Blue(c11) * f11l)>>9
;ici les opérations font déborder le registre, aussi je décale tout de 8 vers la gauche pour garder un peu de marge
;(Blue(c00) * f00l)>>9
MOV eax,c00
BSWAP eax
AND eax,$FF00
IMUL eax,f00l
;(Blue(c10) * f10l)>>9
MOV ebx,c10
BSWAP ebx
AND ebx,$FF00
IMUL ebx,f10l
ADD eax,ebx
;(Blue(c01) * f01l)>>9
MOV ebx,c01
BSWAP ebx
AND ebx,$FF00
IMUL ebx,f01l
ADD eax,ebx
;(Blue(c11) * f11l)>>9
MOV ebx,c11
BSWAP ebx
AND ebx,$FF00
IMUL ebx,f11l
ADD eax,ebx
SAR eax,9
BSWAP eax
AND eax,$00FF0000
OR ecx,eax
;PokeL(u , r|g|b)
MOV eax,u
MOV [eax],ecx
u+w
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
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
Angle = Angle * #Pi / 180 ; On convertit en radian
Cos.f = Cos(Angle)
Sin.f = Sin(Angle)
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) + bm\bmHeight * Abs(Sin)
bmi2\bmiHeader\biHeight = bm\bmHeight * Abs(Cos) + bm\bmWidth * Abs(Sin)
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
CY1 = bm\bmHeight - 1
CX2 = bmi2\bmiHeader\biWidth - 1
CY2 = bmi2\bmiHeader\biHeight - 1
Mem01 = Mem + bm\bmWidth * 4
Mem10 = Mem + 4
Mem11 = Mem01 + 4
For n = 0 To CX2
x1b.l = n * 2 - CX2
Temp1.f = CX1 + x1b * Cos
Temp2.f = CY1 + x1b * Sin
For nn = 0 To CY2
y1b.l = nn * 2 - CY2
x1.f = (Temp1 - y1b * Sin) / 2
y1.f = (Temp2 + y1b * Cos) / 2
x2.l = x1
y2.l = y1
If x1 < x2
DEC x2
EndIf
If y1 < y2
DEC y2
EndIf
x2b = x2 + 1
y2b = y2 + 1
If x2b >= 0 And x2 <= CX1 And y2b >= 0 And y2 <= CY1 ; On filtre si on est completement en dehors de l'image
fx.f = x1 - x2
fy.f = y1 - y2
f00.f = (1 - fx) * (1 - fy)
f01.f = (1 - fx) * fy
f10.f = fx * (1 - fy)
f11.f = fx * fy
MemTemp = (x2 + y2 * bm\bmWidth) * 4
If x2 >= 0 And x2 <= CX1
If y2 >= 0 And y2 <= CY1
c00 = PeekL(Mem + MemTemp)
Else
c00 = 0
EndIf
If y2b >= 0 And y2b <= CY1
c01 = PeekL(Mem01 + MemTemp)
Else
c01 = 0
EndIf
Else
c00 = 0
c01 = 0
EndIf
If x2b >= 0 And x2b <= CX1
If y2 >= 0 And y2 <= CY1
c10 = PeekL(Mem10 + MemTemp)
Else
c10 = 0
EndIf
If y2b >= 0 And y2b <= CY1
c11 = PeekL(Mem11 + MemTemp)
Else
c11 = 0
EndIf
Else
c10 = 0
c11 = 0
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))
Else
PokeL(Mem2 + (n + nn * bmi2\bmiHeader\biWidth) * 4, 0)
EndIf
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 = 4
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