Bon voilà un peu d'asm. On peut faire mieux, mais je fais une pause
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