Rotate images with vfp9 gdiplus and gdiplusX classes
Native gdiplus.vcx shipped with vfp9 is few used by vfp developpers .its a minimalistic class and its not very documented and miss decorated by examples.I dont see VFP developments on the wordl wide web with this class !
gdiplusX translated from .net technology is more reliable and contains more than 600 APIS for drawing technics.
the native vfp9 gdiplus class have the advantage its already in vfp9 IDE (dont need to load it from external file).
image.rotateflip property does some known rotations/flips only for some specific angles:
image.rotateFlip=nValue see in help constantscover 0-7 values.
this dont know how to rotate an image at a given angle.
also vfp image control have not a rotation peoperty in its PEM.
for that purpose and in code *1* need the object gpimage and the object gpGraphics of gdiplus class.
however this is an example demonstrating how rotate an image at any angle 0 to 360 degrees even animated rotations.
note that code use form with showWindow=0,1,2...see the relative handle hwnd in code.
gdiplus nor gdiplusX dont document how to work with form.showWindow=2 (top leve form).I already wrote a previous post on that.
it uses simply to values of form.HWND to achieve this goal
With Thisform
.addproperty("RealHWND",.f.)
.realhwnd = Iif(.ShowWindow = 2, Sys(2327, Sys(2325, Sys(2326,.HWnd))), .HWnd)
Endwith
for more PEM on object gpImage and gpGraphics see in help these chapters:
GDI Plus Graphics Foundation Class
GDI Plus Bitmap Foundation Class
Click on code to select [then copy] -click outside to deselect
*1* rotating an image with native vfp9 gdiplus class
*!* for that purpose need the object gpimage and the object gpGraphics of gdiplus class.
*!* however this is an example demonstrating how rotate an image at any angle 0 to 360 degrees.
*!*note that code use form with showWindow=0,1,2...see the relative handle hwnd in code.
*the code downloads first working image from my blog (or point later on the form to any image on disc)
Declare Integer Sleep In kernel32 Integer
Declare Integer URLDownloadToFile In urlmon.Dll Integer pCaller, String szURL, String szFileName, Integer dwReserved, Integer lpfnCB
Declare Integer DeleteUrlCacheEntry In wininet String lpszUrlName
lcDownloadURL = "http://img.over-blog-kiwi.com/1/43/54/07/20170119/ob_5995a2_ycolorwheel5png.png"
lcDownloadLoc ="ycolorwheel.png"
lnResult = DeleteUrlCacheEntry(lcDownloadURL)
lnResult = URLDownloadToFile(0, lcDownloadURL, lcDownloadLoc , 0,0)
If lnResult = 0
Wait Window "Download "+lcDownloadLoc +" Complete" Nowait
*Else
*!* Messagebox("Download fails")
Endi
Publi yform
yform=Newobject("yrotations")
yform.Show
Read Events
Retu
Define Class yrotations As Form
Top = -1
Left = 17
Height = 577
Width = 962
ShowWindow = 2
ShowTips = .T.
Caption = "Rotate image with vfp9 gdiplus class - artistic effect"
BackColor = Rgb(212,210,208)
realhwnd = .F.
Name = "Form1"
Add Object image1 As Image With ;
Picture = "ycolorwheel.png", ;
Height = 300, ;
Left = 336, ;
Top = 240, ;
Width = 300, ;
Name = "Image1"
Add Object container1 As ycnt With ;
Anchor = 768, ;
Top = 6, ;
Left = 10, ;
Width = 350, ;
Height = 66, ;
BackStyle = 0, ;
BorderWidth = 0, ;
BackColor = Rgb(0,0,0), ;
Name = "Container1"
Add Object shape1 As Shape With ;
Top = 4, ;
Left = 936, ;
Height = 14, ;
Width = 14, ;
Anchor = 768, ;
Curvature = 99, ;
MousePointer = 15, ;
ToolTipText = "Hide/show controls", ;
BackColor = Rgb(255,0,0), ;
Name = "Shape1"
Procedure Init
With Thisform
.realhwnd = Iif(.ShowWindow = 2, Sys(2327, Sys(2325, Sys(2326,.HWnd))), .HWnd)
Endwith
Thisform.WindowState=2
Endproc
Procedure Destroy
Clea Events
Endproc
Procedure Resize
With Thisform.image1
.Left=(Thisform.Width-.Width)/2
.Top=(Thisform.Height-.Height)/2
Endwith
Endproc
Procedure shape1.Click
With Thisform.container1
.Visible=!.Visible
If .Visible=.F.
Set Curs Off
Thisform.container1.command2.Click() &&redraw
Else
Set Curs On
Endi
Endwith
Endproc
Enddefine
*
*-- EndDefine: yrotations
Define Class ycnt As Container
Anchor = 768
Top = 6
Left = 10
Width = 350
Height = 66
BackStyle = 0
BorderWidth = 0
BackColor = Rgb(0,0,0)
Name = "Container1"
Add Object spinner1 As Spinner With ;
Height = 24, ;
Left = 39, ;
SpecialEffect = 2, ;
KeyboardHighValue = 360, ;
KeyboardLowValue = 1, ;
increment=2,;
SpinnerHighValue = 360.00, ;
SpinnerLowValue = 1.00, ;
value=1,;
ToolTipText = "Rotation 1°", ;
Top = 5, ;
Width = 78, ;
Name = "Spinner1"
Add Object check1 As Checkbox With ;
Top = 6, ;
Left = 122, ;
Height = 17, ;
Width = 42, ;
AutoSize = .T., ;
Alignment = 0, ;
BackStyle = 0, ;
Caption = "CLS", ;
Name = "Check1"
Add Object command2 As CommandButton With ;
Top = 6, ;
Left = 170, ;
Height = 27, ;
Width = 96, ;
FontBold = .T., ;
Caption = "Rotate 0-360°", ;
MousePointer = 15, ;
SpecialEffect = 2, ;
BackColor = Rgb(128,255,0), ;
Name = "Command2"
Add Object command1 As CommandButton With ;
Top = 2, ;
Left = 0, ;
Height = 27, ;
Width = 38, ;
FontBold = .T., ;
Caption = "....", ;
MousePointer = 15, ;
ToolTipText = "Get a picture", ;
BackColor = Rgb(255,255,0), ;
Name = "Command1"
Add Object text1 As TextBox With ;
Alignment = 3, ;
Value = 1.00, ;
Height = 25, ;
InputMask = "999.999", ;
Left = 278, ;
ToolTipText = "Scale X", ;
Top = 2, ;
Width = 60, ;
Name = "Text1"
Add Object text2 As TextBox With ;
Alignment = 3, ;
Value = 1.00, ;
Height = 25, ;
InputMask = "999.999", ;
Left = 278, ;
ToolTipText = "scaleY", ;
Top = 29, ;
Width = 60, ;
Name = "Text2"
Add Object command3 As CommandButton With ;
AutoSize = .T., ;
Top = 33, ;
Left = 186, ;
Height = 27, ;
Width = 65, ;
FontBold = .T., ;
Caption = "Capture", ;
MousePointer = 15, ;
BackColor = Rgb(255,128,64), ;
Name = "Command3"
Add Object command4 As CommandButton With ;
AutoSize = .T., ;
Top = 34, ;
Left = 4, ;
Height = 27, ;
Width = 43, ;
FontBold = .T., ;
Caption = "CLS", ;
MousePointer = 15, ;
BackColor = Rgb(128,0,255), ;
Name = "Command4"
Add Object spinner2 As Spinner With ;
Comment = "30", ;
Height = 24, ;
KeyboardHighValue = 360, ;
KeyboardLowValue = 1, ;
Left = 55, ;
SpinnerHighValue = 360.00, ;
SpinnerLowValue = 1.00, ;
ToolTipText = "nStep", ;
Top = 37, ;
Width = 91, ;
Value = 10, ;
Name = "Spinner2"
Procedure spinner1.InteractiveChange
Local loimage As gpimage Of ffc/_gdiplus.vcx
loimage = Newobject("gpimage",Home()+"ffc/_gdiplus.vcx")
loimage.createfromfile(Thisform.image1.Picture)
Thisform.image1.Visible=.T.
x0=Thisform.image1.Left+Thisform.image1.Width/2
y0=Thisform.image1.Top+Thisform.image1.Height/2
gfx=Newobject("gpGraphics",Home()+"ffc/_gdiplus.vcx")
gfx.createfromhwnd(Thisform.realhwnd) && form.showWindow=0,1 ,t 2
If This.Parent.check1.Value=1
Thisform.Cls
Endi
* rotate the gfx
gfx.translatetransform(x0, y0)
gfx.rotatetransform(This.Value)
gfx.translatetransform(- x0, - y0)
gfx.ScaleTransform(This.Parent.text1.Value, This.Parent.text2.Value)
* draw image
gfx.drawImageAt(loimage,x0,y0)
* restore the original gfx rotation state
gfx.resettransform()
gfx=Null
loimage=Null
Endproc
Procedure command2.Click
Local loimage As gpimage Of ffc/_gdiplus.vcx
loimage = Newobject("gpimage",Home()+"ffc/_gdiplus.vcx")
loimage.createfromfile(Thisform.image1.Picture)
x0=Thisform.image1.Left+Thisform.image1.Width/2
y0=Thisform.image1.Top+Thisform.image1.Height/2
Thisform.ForeColor=255
Thisform.Line(x0,0,x0,2*y0)
Thisform.Line(0,y0,2*x0,y0)
gfx=Newobject("gpGraphics",Home()+"ffc/_gdiplus.vcx")
gfx.createfromhwnd(Thisform.realhwnd) && form.showWindow=0,1 ,t 2
Local nstep
nstep=Thisform.container1.spinner2.Value
For i=0 To 360 Step nstep
If This.Parent.check1.Value=1
Thisform.Cls
Endi
*rotate the gfx
gfx.translatetransform(x0, y0)
gfx.rotatetransform(i)
gfx.translatetransform(- x0, - y0)
gfx.ScaleTransform(This.Parent.text1.Value, This.Parent.text2.Value)
*draw image
gfx.drawImageAt(loimage,x0,y0)
*restore the original gfx rotation state
gfx.resettransform()
Inke(0.1)
Endfor
gfx=Null
loimage=Null
Endproc
Procedure command1.Click
Local m.xpict
m.xpict=Getpict()
If !Empty(m.xpict)
Thisform.image1.Picture=m.xpict
Endi
Endproc
Procedure command3.Click
Try
Run/N snippingtool.Exe
Catch
Messagebox("Snippingtool not installed !",16+4096)
Endtry
Endproc
Procedure command4.Click
Thisform.Cls
Endproc
Enddefine
*
*-- EndDefine:ycnt
variying nstep in spinner2 can obtain various artistic rendered images.
Click on code to select [then copy] -click outside to deselect
*2* using gdiplusX class to rotate an image
*modifying nstep can give many results.
*can transpose the form of code *1* here for visual demo to user.
*here drawing is not cleared to leave some image effects by rotation.
LOCAL lcSource, lnWidth, lnHeight
lcSource = GETPICT()
IF EMPTY(lcSource)
RETURN
ENDIF
DO LOCFILE("System.App")
set defa to addbs(justpath(sys(16,1)))
WITH _SCREEN.System.Drawing
LOCAL loBmp0,loBMP AS xfcBitmap
loBMP0=.bitmap.new(_screen.width,_screen.height)
logfx= .Graphics.FromImage(loBmp0)
logfx.clear(.color.white)
xc=_screen.width/2
yc=_screen.height/2
loBmp = .Bitmap.FromFile(lcSource)
w=loBMP.width/2
h=loBMP.height/2
local nstep
nstep=10 &&can modify for difrent results
oState = loGfx.Save()
loGfx.TranslateTransform(xc,yc)
for i=0 to 360 step nstep
loGfx.RotateTransform(i)
loGfx.DrawImage(loBmp,0,0,w,h)
endfor
PEN = .PEN.NEW(.color.red, 4)
loGfx.DrawEllipse(pen,0,0,5,5)
loGfx.restore(oState)
local m.lcdest
m.lcdest="miror.png"
loBmp0.Save(m.lcdest, .Imaging.ImageFormat.Png)
RUN /N "mspaint" &lcdest
endwith
retu
varying nstep in loop produces difrent results.
Important:All Codes above are tested on VFP9SP2 & windows 10 pro