Rotation image de qualité
Publié : ven. 27/juil./2012 17:33
Exécuter une rotation à une image est assez simple mais quand on l'imprime, c'est vraiment moche alors j'ai trouvé divers codes qui permettent une rotation de qualité comme celui-ci :
L'embêtant, c'est que la rotation se fait sur le point milieu de l'image en x et en y, le pivot a pour coordonnées (width/2, height/2) et je voudrais faire une rotation à partir de n'importe quel point.
De plus, je n’arrive pas à retrouver la formule de rotation dans ce code.:
pivot(x0,y0)
X=x0 + (x - x0)*cos(angle) + (y - y0)*sin(Angle)
Y=y0 - (x - x0)*sin(Angle) + (y - y0)*cos(Angle)
Il semble que l'auteur utilise des astuces de calcul pour simplifier son code...
Je cherche à faire ceci :
RotateImageEx2(ImageID, Angle.f, Pivotx, Pivoty, ColeurFond=#Black)
Une idée ?
Mesa.
Code : Tout sélectionner
;Fast and clean rotation
;Original Code : LSI (le soldat inconnu) for his effects library (http://www.purearea.net/pb/download/userlibs/Effect.zip)
;Optimisation (not fully optimised) by djes (djes@free.fr)
;Not needing assembly inline by psychophanta
;#PI.f=3.14159265
;******************************************************************************************************
; RotateImageEx2
;>= Angle (in degrees :()
ProcedureDLL.l RotateImageEx2(ImageID, Angle.f,ColeurFond=#Black)
Protected bmi.BITMAPINFO, bmi2.BITMAPINFO, Hdc.l, NewImageID, Mem, n, nn, bm.BITMAP
;radian conversion
;Debug "Angle : "+Str(angle)
Angle*#PI/180
Protected Cos.f = Cos(Angle)
Protected Sin.f = Sin(Angle)
ColeurFond=ColeurFond&$ff00 | ColeurFond>>16 | (ColeurFond&$FF)<<16
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
; Debug bm\bmWidth
; Debug bm\bmHeight
Mem = AllocateMemory(bm\bmWidth * bm\bmHeight * 4)
If Mem
Protected Mem2 = AllocateMemory(bmi2\bmiHeader\biWidth * bmi2\bmiHeader\biHeight * 4)
If Mem2
;retrieves the bits of the specified bitmap and copies them into a buffer
Hdc = CreateCompatibleDC_(GetDC_(ImageID))
If Hdc
GetDIBits_(Hdc, ImageID, 0, bm\bmHeight, Mem, @bmi, #DIB_RGB_COLORS)
ReleaseDC_(0, Hdc)
EndIf
Protected CX1 = bm\bmWidth - 1
Protected CY1 = bm\bmHeight - 1
Protected CX2 = bmi2\bmiHeader\biWidth - 1
Protected CY2 = bmi2\bmiHeader\biHeight - 1
Protected Mem01 = Mem + bm\bmWidth * 4
Protected Mem10 = Mem + 4
Protected Mem11 = Mem01 + 4
Protected Mem2Temp = Mem2
Protected deb=-CX2/2
Protected fin=deb+CX2;= Round(CX2/2,#PB_Round_Up) but <> (CX2*2-CX2)/2
For nn = 0 To CY2 ;y
Protected x1b.l
Protected y1b.l = (nn * 2) - CY2
Protected Temp1.f = (CX1 - (y1b * Sin))/2
Protected Temp2.f = (CY1 + (y1b * Cos))/2
Protected x1.f = Temp1 + (deb * Cos)
Protected y1.f = Temp2 + (deb * Sin)
For x1b = deb To fin ;x
;could be faster with arrays
Protected x2.l = x1
Protected y2.l = y1
If x1 < x2
!dec dword[p.v_x2]
EndIf
If y1 < y2
!dec dword[p.v_y2]
EndIf
Protected x2b.l = x2 + 1
Protected y2b.l = y2 + 1
;test boundaries
If x2b >= 0 And x2 <= CX1 And y2b >= 0 And y2 <= CY1
Protected fx.f = x1 - x2
Protected fy.f = y1 - y2
Protected f00.f = 1 - fx
Protected f10.f = 1 - fy
Protected f01.f = f00 * fy
f00 * f10
f10 * fx
Protected f11.f = fx * fy
Protected MemTemp = (x2 + y2 * bm\bmWidth) * 4
Protected c00.l, c01.l, c11.l, c10.l
If x2 >= 0 And x2 <= CX1
If y2 >= 0 And y2 <= CY1
!mov eax,dword[p.v_Mem]
!add eax,dword[p.v_MemTemp]
!mov eax,dword[eax]
!mov dword[p.v_c00],eax
;c00 = PeekL(Mem + MemTemp)
Else
c00 = 0
EndIf
If y2b >= 0 And y2b <= CY1
!mov eax,dword[p.v_Mem01]
!add eax,dword[p.v_MemTemp]
!mov eax,dword[eax]
!mov dword[p.v_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,dword[p.v_Mem10]
!add eax,dword[p.v_MemTemp]
!mov eax,dword[eax]
!mov dword[p.v_c10],eax
;c10 = PeekL(Mem10 + MemTemp)
Else
c10 = 0
EndIf
If y2b >= 0 And y2b <= CY1
!mov eax,dword[p.v_Mem11]
!add eax,dword[p.v_MemTemp]
!mov eax,dword[eax]
!mov dword[p.v_c11],eax
;c11 = PeekL(Mem11 + MemTemp)
Else
c11 = 0
EndIf
Else
c10 = 0
c11 = 0
EndIf
Protected r1.l,r2.l,r3.l,r4.l,g1.l,g2.l,g3.l,g4.l,b1.l,b2.l,b3.l,b4.l
!mov eax,dword[p.v_c00]
!mov ebx,eax
!mov ecx,eax
!and eax,$FF
!mov dword[p.v_r1],eax
!and ebx,$FF00
!mov dword[p.v_g1],ebx
!and ecx,$FF0000
!mov dword[p.v_b1],ecx
!mov eax,dword[p.v_c10]
!mov ebx,eax
!mov ecx,eax
!and eax,$FF
!mov dword[p.v_r2],eax
!and ebx,$FF00
!mov dword[p.v_g2],ebx
!and ecx,$FF0000
!mov dword[p.v_b2],ecx
!mov eax,dword[p.v_c01]
!mov ebx,eax
!mov ecx,eax
!and eax,$FF
!mov dword[p.v_r3],eax
!and ebx,$FF00
!mov dword[p.v_g3],ebx
!and ecx,$FF0000
!mov dword[p.v_b3],ecx
!mov eax,dword[p.v_c11]
!mov ebx,eax
!mov ecx,eax
!and eax,$FF
!mov dword[p.v_r4],eax
!and ebx,$FF00
!mov dword[p.v_g4],ebx
!and ecx,$FF0000
!mov dword[p.v_b4],ecx
;pure knows well how to do this
Protected r.l = r1 * f00 + r2 * f10 + r3 * f01 + r4 * f11
Protected g.l = g1 * f00 + g2 * f10 + g3 * f01 + g4 * f11
Protected b.l = b1 * f00 + b2 * f10 + b3 * f01 + b4 * f11
!mov eax,dword[p.v_r]
!mov ebx,dword[p.v_g]
!mov ecx,dword[p.v_b]
;one trick is to let triplets at the same place to avoid shifting
!and eax,$FF
!and ebx,$FF00
!and ecx,$FF0000
!or eax,ebx
!or eax,ecx
!mov ebx,dword[p.v_Mem2Temp]
!mov dword[ebx],eax
Else
!mov ebx,dword[p.v_Mem2Temp]
;!xor eax,eax; black background
!mov eax,dword[p.v_ColeurFond]; user defined background
!mov dword[ebx],eax
EndIf
Mem2Temp + 4
x1 + cos
y1 + sin
Next x1b
Next nn
; On crée la nouvelle image
NewImageID = CreateImage(#PB_Any, bmi2\bmiHeader\biWidth, bmi2\bmiHeader\biHeight)
Hdc = CreateCompatibleDC_(GetDC_(ImageID(NewImageID)))
If Hdc
SetDIBits_(Hdc, ImageID(NewImageID), 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
;******************************************************************************************************
;{- Enumerations / DataSections
;{ Windows
Enumeration
#Window_0
EndEnumeration
;}
;{ Gadgets
Enumeration
#ScrollArea_0
#Image_1
EndEnumeration
;}
;{ Images
Enumeration
#Image_Image_1
EndEnumeration
;}
Define.l Event, EventWindow, EventGadget, EventType, EventMenu
;}
Procedure OpenWindow_Window_0()
If OpenWindow(#Window_0, 381, 30, 625, 628, "Window_0", #PB_Window_SystemMenu|#PB_Window_SizeGadget|#PB_Window_MinimizeGadget|#PB_Window_TitleBar)
ScrollAreaGadget(#ScrollArea_0, 5, 10, 610, 605, 3000, 3000, 10, #PB_ScrollArea_Single)
ImageGadget(#Image_1, 10, 15, 405, 320, 0, #PB_Image_Border)
CloseGadgetList()
EndIf
EndProcedure
OpenWindow_Window_0()
ImageID=CreateImage(#PB_Any,200,200)
StartDrawing(ImageOutput(ImageID))
Box(0,0,200-1,200-1,#White)
For Angle = 0 To 360 Step 3
LineXY(100, 100, 100+Cos(Angle)*90, 100+Sin(Angle)*90, RGB(Random(255), Random(255), Random(255)))
Next Angle
Box(0,100,200-1,200-1,#Red)
StopDrawing()
SetGadgetState(#Image_1,ImageID(ImageID))
;Im1=LoadImage(#PB_Any,"ok.bmp")
;GrabImage(Im1, ImageID, 0, 0, 245, 720)
;Je recherche un RotateImageEx2(ImageID, Angle.f, Pivotx, Pivoty, ColeurFond=#Black)
im2=RotateImageEx2(ImageID(ImageID), 30, #White)
SetGadgetState(#Image_1,ImageID(Im2))
;{- Event loop
Repeat
Event = WaitWindowEvent()
Select Event
; ///////////////////
Case #PB_Event_Gadget
EventGadget = EventGadget()
EventType = EventType()
If EventGadget = #ScrollArea_0
ElseIf EventGadget = #Image_1
EndIf
; ////////////////////////
Case #PB_Event_CloseWindow
EventWindow = EventWindow()
If EventWindow = #Window_0
CloseWindow(#Window_0)
Break
EndIf
EndSelect
ForEver
;
;}
De plus, je n’arrive pas à retrouver la formule de rotation dans ce code.:
pivot(x0,y0)
X=x0 + (x - x0)*cos(angle) + (y - y0)*sin(Angle)
Y=y0 - (x - x0)*sin(Angle) + (y - y0)*cos(Angle)
Il semble que l'auteur utilise des astuces de calcul pour simplifier son code...
Je cherche à faire ceci :
RotateImageEx2(ImageID, Angle.f, Pivotx, Pivoty, ColeurFond=#Black)
Une idée ?
Mesa.