Friday, February 02, 2007

Creating Gradient Images the Fast and Easy Way

I've been trying to spiff up some forms lately. One way to make an attractive form is to use some graphic elements. I particularly like gradient images, as illustrated in this screen shot (the gradient appears banded in this image but not in the actual form):



So, how to create a gradient image of the desired size and color? Although I could do it dynamically using the VFPX GDIPlusX library as described by Cesar Chalom in various posting on his excellent blog, I decided to simply create an image file and use it as the Picture property of an Image object.

With some help from Cesar's blog, I created a simple program, CreateGradient.PRG, that generates a gradient image with the specified file name, size, and colors. The code is self-explanatory. Note that it expects the GDIPlusX class libraries are in the VFP path.
lparameters tcFileName, ;
tnHeight, ;
tnWidth, ;
tnColor1, ;
tnColor2
local lnColor1, ;
lnColor2, ;
lnMode, ;
lnFormat, ;
loSystem, ;
lcExt, ;
loBitmap, ;
loRect, ;
loGfx, ;
loGradBrush

* Ensure the parameters were passed.

if vartype(tcFileName) <> 'C' or empty(tcFileName) or ;
vartype(tnHeight) <> 'N' or vartype(tnWidth) <> 'N'
error 11
return .F.
endif vartype(tcFileName) <> 'C' ...

* If colors weren't passed, prompt for them.

if pcount() < 4
lnColor2 = getcolor(rgb( 0, 128, 255))
lnColor1 = getcolor(rgb(255, 255, 255))
else
lnColor1 = tnColor1
lnColor2 = tnColor2
endif pcount() < 4

* This assumes a horizontal gradient. Set lnMode to a different
* value for other types.

lnMode = 0


* Create a GDIPlusX System object.

loSystem = newobject('xfcSystem', 'System.vcx')
with loSystem.Drawing

* Determine the image type from the file extension.

lcExt = upper(justext(tcFileName))
do case
case lcExt = 'PNG'
lnFormat = .Imaging.ImageFormat.Png
case lcExt = 'BMP'
lnFormat = .Imaging.ImageFormat.Bmp
case lcExt = 'GIF'
lnFormat = .Imaging.ImageFormat.Gif
case inlist(lcExt, 'JPG', 'JPEG')
lnFormat = .Imaging.ImageFormat.Jpeg
case lcExt = 'ICO'
lnFormat = .Imaging.ImageFormat.Icon
case inlist(lcExt, 'TIF', 'TIFF')
lnFormat = .Imaging.ImageFormat.Tiff
case lcExt = 'WMF'
lnFormat = .Imaging.ImageFormat.Wmf
otherwise
error 11
return .F.
endcase

* Create a bitmap and a rectangle of the desired size.

loBitmap = .Bitmap.New(tnWidth, tnHeight)
loRect = .Rectangle.New(0, 0, tnWidth, tnHeight)

* Create a graphics object.

loGfx = .Graphics.FromImage(loBitmap)
loGfx.Clear(.Color.White)

* Create a linear gradient brush.

loGradBrush = .Drawing2D.LinearGradientBrush.New(loRect, ;
.Color.FromRgb(lnColor1), .Color.FromRgb(lnColor2), lnMode)

* Fill the rectangle with the gradient brush.

loGfx.FillRectangle(loGradBrush, loRect)

* Save the image to the specified file.

loBitmap.Save(tcFileName, lnFormat)
endwith
return
Thanks to Craig Boyd, Bo Durban, and Cesar for all the work they've done on this incredible library!

3 comments:

Anonymous said...

Hey Doug !
It's great to see you working with the library!
Of course we all know that there are many ways to skin a fox! :-)

Just added this link to the library references at Codeplex http://www.codeplex.com/VFPX/Wiki/View.aspx?title=GDIPlusX%20References&referringTitle=GDIPlusX

We want more !
We want more !

Anonymous said...

>>the gradient appears banded in this image but not in the actual form

That image effect was caused probably because you've saved that screenshot as a GIF with an application that uses GDI+.

When working with GIFs, GDI+ works with a fixed color palette of 216 'Web-safe colors', what brings some ugly results.

Well, let me make an advertisement here... With GdiPlus-X we'll add the possibility to fix this native "bad" behavior of gdiplus.dll, by checking the colors used, and recreating the color palette with the 256 colors that will produce the best result.

Anonymous said...

Just want to add my thanks to Cesar and Bo and whoever else did this work. It saved my bacon today in a project where I needed to be able to print complex forms that weren't amenable to typical reports.