
pour l'instant , the winner is "le dernier code de djes 257 ms"
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
Mem2Temp = Mem2
For nn = 0 To CY2
y1b.l = nn * 2 - CY2
Temp1.f = CX1 - y1b * Sin
Temp2.f = CY1 + y1b * Cos
For n = 0 To CX2
x1b.l = n * 2 - CX2
x1.f = (Temp1 + x1b * Cos) / 2
y1.f = (Temp2 + x1b * Sin) / 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(Mem2Temp, RGB(r, g, b))
Else
PokeL(Mem2Temp, 0)
EndIf
Mem2Temp + 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 = 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
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
X = bm\bmWidth
Y = bm\bmHeight
Mem = AllocateMemory(6 * 4)
If Mem
; On récupère l'image dans un espace mémoire
Hdc = GetDC_(0) ; CreateCompatibleDC_(GetDC_(ImageID))
If Hdc
HCDC = CreateCompatibleDC_(Hdc)
SelectObject_(HCDC, ImageID)
; On fait la rotation de l'image de 90, 180 ou 270°
Select Angle
Case 90 ; rotation de 90°
; Point haut gauche
PokeL(Mem, bm\bmHeight)
; PokeL(Mem + 4, 0)
; Point haut droit
PokeL(Mem + 8, bm\bmHeight)
PokeL(Mem + 12, bm\bmWidth)
; Point bas gauche
; PokeL(Mem+ 16, 0)
; PokeL(Mem + 20, 0)
Temp1 = bm\bmHeight : bm\bmHeight = bm\bmWidth : bm\bmWidth = Temp1
NewImageID = CreateImage(#PB_Any, bm\bmWidth, bm\bmHeight)
Case 180
; Point haut gauche
PokeL(Mem, bm\bmWidth)
PokeL(Mem + 4, bm\bmHeight)
; Point haut droit
; PokeL(Mem + 8,0)
PokeL(Mem + 12, bm\bmHeight)
; Point bas gauche
PokeL(Mem+ 16, bm\bmWidth)
; PokeL(Mem + 20, 0)
NewImageID = CreateImage(#PB_Any, bm\bmWidth, bm\bmHeight)
Case 270
; Point haut gauche
; PokeL(Mem, 0)
PokeL(Mem + 4, bm\bmWidth)
; Point haut droit
; PokeL(Mem + 8, 0t)
; PokeL(Mem + 12, 0)
; Point bas gauche
PokeL(Mem+ 16, bm\bmHeight)
PokeL(Mem + 20, bm\bmWidth)
Temp1 = bm\bmHeight : bm\bmHeight = bm\bmWidth : bm\bmWidth = Temp1
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
HCDC2 = CreateCompatibleDC_(Hdc)
SelectObject_(HCDC2, UseImage(NewImageID))
If HCDC2
PlgBlt_(HCDC2, Mem, HCDC, 0, 0, bm\bmHeight, bm\bmWidth, 0, 0, 0)
DeleteDC_(HCDC2)
EndIf
DeleteDC_(HCDC)
ReleaseDC_(0, Hdc)
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 = 4
Temps1 = ElapsedMilliseconds()
For n = 1 To #NbTest
ImageModifiee = RotateImage2(ImageOrigine, 90)
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 = RotateImage2(UseImage(ImageNormale), 90)
; 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
pas saisi ou tu veux utiliser ceci ?Pour ta routine, y'a aussi moyen de charger par gros paquets (multiples de 8 ou 16?) plutôt qu'à l'unité; je ne me souviens plus des instructions mais je sais que c'est possible!
Je parlais des routines de symétrie/rotation 90, 180, 270. Pour la rotation, effectivement, l'utilisation des entiers ne s'impose pas, voire est plus lente! Je vais pour ma part faire la partie asm pour virer les CALL (fonctions pure poke, peek, rgb)...Le Soldat Inconnu a écrit :pas saisi ou tu veux utiliser ceci ?Pour ta routine, y'a aussi moyen de charger par gros paquets (multiples de 8 ou 16?) plutôt qu'à l'unité; je ne me souviens plus des instructions mais je sais que c'est possible!
Sur mon XP2000+ ton code et le mien (le tout dernier) sont aussi rapide.
Je vais combiné les codes dessus pour voir si j'obtiens un gain supplémentaire (normalement oui)
Bon, sinon, j'ai optimiser encore un poil la rotation de 90, 180, 270° et la symétrie d'image
Et j'ai mis à jour la lib sur mon site.
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
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
Mem2Temp = Mem2
For nn = 0 To CY2
y1b.l = nn * 2 - CY2
Temp1.f = (CX1 - y1b * Sin)/2
Temp2.f = (CY1 + y1b * Cos)/2
For x1b = -CX2/2 To (CX2*2-CX2)/2
x1.f = Temp1 + x1b * Cos ;on pourrait virer ces mult avec des tables mais le gain n'est pas évident
y1.f = Temp2 + x1b * Sin
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
f10.f = 1 - fy
f01.f = f00 * fy
f00 * f10
f10 * fx
f11.f = fx * fy
MemTemp = (x2 + y2 * bm\bmWidth) * 4
DefType.l c00, c01, c11, c10
If x2 >= 0 And x2 <= CX1
If y2 >= 0 And y2 <= CY1
MOV eax,mem
ADD eax,memtemp
MOV eax,[eax]
MOV c00,eax
;c00 = PeekL(Mem + MemTemp)
Else
c00 = 0
EndIf
If y2b >= 0 And y2b <= CY1
MOV eax,mem01
ADD eax,memtemp
MOV eax,[eax]
MOV c01,eax
;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
MOV eax,mem10
ADD eax,memtemp
MOV eax,[eax]
MOV c10,eax
;c10 = PeekL(Mem10 + MemTemp)
Else
c10 = 0
EndIf
If y2b >= 0 And y2b <= CY1
MOV eax,mem11
ADD eax,memtemp
MOV eax,[eax]
MOV c11,eax
;c11 = PeekL(Mem11 + MemTemp)
Else
c11 = 0
EndIf
Else
c10 = 0
c11 = 0
EndIf
DefType.l r1,r2,r3,r4 , g1,g2,g3,g4 , b1,b2,b3,b4
MOV eax,c00
MOV ebx,eax
MOV ecx,eax
AND eax,$FF
MOV r1,eax
AND ebx,$FF00
MOV g1,ebx
AND ecx,$FF0000
MOV b1,ecx
MOV eax,c10
MOV ebx,eax
MOV ecx,eax
AND eax,$FF
MOV r2,eax
AND ebx,$FF00
MOV g2,ebx
AND ecx,$FF0000
MOV b2,ecx
MOV eax,c01
MOV ebx,eax
MOV ecx,eax
AND eax,$FF
MOV r3,eax
AND ebx,$FF00
MOV g3,ebx
AND ecx,$FF0000
MOV b3,ecx
MOV eax,c11
MOV ebx,eax
MOV ecx,eax
AND eax,$FF
MOV r4,eax
AND ebx,$FF00
MOV g4,ebx
AND ecx,$FF0000
MOV b4,ecx
r = r1 * f00 + r2 * f10 + r3 * f01 + r4 * f11 ;pure fait très bien tout ça
g = g1 * f00 + g2 * f10 + g3 * f01 + g4 * f11
b = b1 * f00 + b2 * f10 + b3 * f01 + b4 * f11
MOV eax,r
MOV ebx,g
MOV ecx,b
AND eax,$FF ;toute l'astuce consiste à laisser les triplets à leur place et à les multiplier là. On évite ainsi les décalages
AND ebx,$FF00
AND ecx,$FF0000
OR eax,ebx
OR eax,ecx
MOV ebx,Mem2Temp
MOV [ebx],eax
Else
MOV ebx,Mem2Temp
XOR eax,eax
MOV [ebx],eax
EndIf
Mem2Temp + 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 = 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
; ExecutableFormat=
; EnableAsm
; DisableDebugger
; EOF
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
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
Mem2Temp = Mem2
deb=-CX2/2 : fin=(CX2*2-CX2)/2
For nn = 0 To CY2
y1b.l = nn * 2 - CY2
Temp1.f = (CX1 - y1b * Sin)/2
Temp2.f = (CY1 + y1b * Cos)/2
For x1b = deb To fin
x1.f = Temp1 + x1b * Cos ;on pourrait virer ces mult avec des tables mais le gain n'est pas évident
y1.f = Temp2 + x1b * Sin
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
f10.f = 1 - fy
f01.f = f00 * fy
f00 * f10
f10 * fx
f11.f = fx * fy
MemTemp = (x2 + y2 * bm\bmWidth) * 4
DefType.l c00, c01, c11, c10
If x2 >= 0 And x2 <= CX1
If y2 >= 0 And y2 <= CY1
MOV eax,mem
ADD eax,memtemp
MOV eax,[eax]
MOV c00,eax
;c00 = PeekL(Mem + MemTemp)
Else
c00 = 0
EndIf
If y2b >= 0 And y2b <= CY1
MOV eax,mem01
ADD eax,memtemp
MOV eax,[eax]
MOV c01,eax
;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
MOV eax,mem10
ADD eax,memtemp
MOV eax,[eax]
MOV c10,eax
;c10 = PeekL(Mem10 + MemTemp)
Else
c10 = 0
EndIf
If y2b >= 0 And y2b <= CY1
MOV eax,mem11
ADD eax,memtemp
MOV eax,[eax]
MOV c11,eax
;c11 = PeekL(Mem11 + MemTemp)
Else
c11 = 0
EndIf
Else
c10 = 0
c11 = 0
EndIf
DefType.l r1,r2,r3,r4 , g1,g2,g3,g4 , b1,b2,b3,b4
MOV eax,c00
MOV ebx,eax
MOV ecx,eax
AND eax,$FF
MOV r1,eax
AND ebx,$FF00
MOV g1,ebx
AND ecx,$FF0000
MOV b1,ecx
MOV eax,c10
MOV ebx,eax
MOV ecx,eax
AND eax,$FF
MOV r2,eax
AND ebx,$FF00
MOV g2,ebx
AND ecx,$FF0000
MOV b2,ecx
MOV eax,c01
MOV ebx,eax
MOV ecx,eax
AND eax,$FF
MOV r3,eax
AND ebx,$FF00
MOV g3,ebx
AND ecx,$FF0000
MOV b3,ecx
MOV eax,c11
MOV ebx,eax
MOV ecx,eax
AND eax,$FF
MOV r4,eax
AND ebx,$FF00
MOV g4,ebx
AND ecx,$FF0000
MOV b4,ecx
r = r1 * f00 + r2 * f10 + r3 * f01 + r4 * f11 ;pure fait très bien tout ça
g = g1 * f00 + g2 * f10 + g3 * f01 + g4 * f11
b = b1 * f00 + b2 * f10 + b3 * f01 + b4 * f11
MOV eax,r
MOV ebx,g
MOV ecx,b
AND eax,$FF ;toute l'astuce consiste à laisser les triplets à leur place et à les multiplier là. On évite ainsi les décalages
AND ebx,$FF00
AND ecx,$FF0000
OR eax,ebx
OR eax,ecx
MOV ebx,Mem2Temp
MOV [ebx],eax
Else
MOV ebx,Mem2Temp
XOR eax,eax
MOV [ebx],eax
EndIf
Mem2Temp + 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é
SetPriorityClass_(GetCurrentProcess_(),#REALTIME_PRIORITY_CLASS)
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)
SetPriorityClass_(GetCurrentProcess_(),#NORMAL_PRIORITY_CLASS)
; 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, CouleurFond)
Protected bmi.BITMAPINFO, bmi2.BITMAPINFO, hdc.l, NewImageID, Mem, n, nn, bm.BITMAP
Angle = Angle * #Pi / 180
Cos.f = Cos(Angle)
Sin.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 = 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)
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
Mem2Temp = Mem2
deb=-CX2/2 : fin=(CX2*2-CX2)/2
For nn = 0 To CY2
y1b.l = nn * 2 - CY2
Temp1.f = (CX1 - y1b * Sin)/2
Temp2.f = (CY1 + y1b * Cos)/2
For x1b = deb To fin
x1.f = Temp1 + x1b * Cos
y1.f = Temp2 + x1b * Sin
x2.l = x1
y2.l = y1
If x1 < x2
DEC x2
EndIf
If y1 < y2
DEC y2
EndIf
x2b = x2 + 1
y2b = y2 + 1
fx.f = x1 - x2
fy.f = y1 - y2
f00.f = 1 - fx
f10.f = 1 - fy
f01.f = f00 * fy
f00 * f10
f10 * fx
f11.f = fx * fy
MemTemp = (x2 + y2 * bm\bmWidth) * 4
DefType.l c00, c01, c11, c10
If x2 >= 0 And x2 <= CX1
If y2 >= 0 And y2 <= CY1
MOV Eax,Mem
ADD Eax,MemTemp
MOV Eax,[Eax]
MOV c00,Eax
Else
c00 = CouleurFond
EndIf
If y2b >= 0 And y2b <= CY1
MOV Eax,Mem01
ADD Eax,MemTemp
MOV Eax,[Eax]
MOV c01,Eax
Else
c01 = CouleurFond
EndIf
Else
c00 = CouleurFond
c01 = CouleurFond
EndIf
If x2b >= 0 And x2b <= CX1
If y2 >= 0 And y2 <= CY1
MOV Eax,Mem10
ADD Eax,MemTemp
MOV Eax,[Eax]
MOV c10,Eax
Else
c10 = CouleurFond
EndIf
If y2b >= 0 And y2b <= CY1
MOV Eax,Mem11
ADD Eax,MemTemp
MOV Eax,[Eax]
MOV c11,Eax
Else
c11 = CouleurFond
EndIf
Else
c10 = CouleurFond
c11 = CouleurFond
EndIf
DefType.l r1,r2,r3,r4 , g1,g2,g3,g4 , b1,b2,b3,b4
MOV Eax,c00
MOV Ebx,Eax
MOV Ecx,Eax
And Eax,$FF
MOV r1,Eax
And Ebx,$FF00
MOV g1,Ebx
And Ecx,$FF0000
MOV b1,Ecx
MOV Eax,c10
MOV Ebx,Eax
MOV Ecx,Eax
And Eax,$FF
MOV r2,Eax
And Ebx,$FF00
MOV g2,Ebx
And Ecx,$FF0000
MOV b2,Ecx
MOV Eax,c01
MOV Ebx,Eax
MOV Ecx,Eax
And Eax,$FF
MOV r3,Eax
And Ebx,$FF00
MOV g3,Ebx
And Ecx,$FF0000
MOV b3,Ecx
MOV Eax,c11
MOV Ebx,Eax
MOV Ecx,Eax
And Eax,$FF
MOV r4,Eax
And Ebx,$FF00
MOV g4,Ebx
And Ecx,$FF0000
MOV b4,Ecx
r = r1 * f00 + r2 * f10 + r3 * f01 + r4 * f11
g = g1 * f00 + g2 * f10 + g3 * f01 + g4 * f11
b = b1 * f00 + b2 * f10 + b3 * f01 + b4 * f11
MOV Eax,r
MOV Ebx,g
MOV Ecx,b
And Eax,$FF
And Ebx,$FF00
And Ecx,$FF0000
Or Eax,Ebx
Or Eax,Ecx
MOV Ebx,Mem2Temp
MOV [Ebx],Eax
Mem2Temp + 4
Next
Next
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
CreateImage(0, 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()
OpenWindow(0, 0, 0, 250, 300, #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget, "Effect - Rotation d'image")
CreateGadgetList(WindowID())
TextGadget(0, 10, 10, 100, 15, "Image normale")
ImageGadget(1, 10, 25, 0, 0, UseImage(0))
TextGadget(2, 10, 135, 200, 15, "Image en rotation")
ImageGadget(3, 10, 150, 0, 0, 0)
CouleurFond = $AAFFAA
SetTimer_(WindowID(),0,1,0)
Repeat
Select WaitWindowEvent()
Case #WM_CLOSE : Break
Case #WM_TIMER
If Image
FreeImage(Image)
EndIf
Angle.f + 0.666666
If Angle > 360.0
Angle = 0
EndIf
Image.l = RotateImageEx2(UseImage(0),Angle,CouleurFond)
ResizeGadget(3,0,WindowHeight()-ImageHeight(),-1,-1)
SetGadgetState(3,UseImage(Image))
EndSelect
ForEver
KillTimer_(WindowID(),0)