HOW TO: Save Images in different formats with GdiPlus-X

That's a very easy task for Gdiplus-X:


All samples below use the Gdiplus-x library. Get the latest stable release from codeplex:


do locfile("system.app")

with _screen.system.drawing

   local mybitmap as xfcbitmap
   && create a bitmap object
   mybitmap = .bitmap.new(getpict())

   && save the bitmap in different formats
   mybitmap.save("c:\mypng.png", .imaging.imageformat.png)
save("c:\mybmp.bmp", .imaging.imageformat.bmp)
save("c:\mytiff.tif", .imaging.imageformat.tiff)
save("c:\myjpeg.jpg", .imaging.imageformat.jpeg)
save("c:\mygif.gif", .imaging.imageformat.gif)


Of course, you can save as jpeg using the quality compression encoder parameter:
The sample below asks for an image and saves it as JPEG with quality 25. Try the values from 0 to 100.

do locfile("system.app")

with _screen.system.drawing

   local mybitmap as xfcbitmap
   local myencoderparameter as xfcencoderparameter
   local myencoderparameters as xfcencoderparameters
   && create a bitmap object based on a bmp file.
   mybitmap = .bitmap.new(getpict("bmp"))

   && create an encoderparameters object.
   && an encoderparameters object has an array of encoderparameter objects
   && in this case, there is only one encoderparameter object in the array.
   myencoderparameters = .imaging.encoderparameters.new(1)

   && save the bitmap as a jpeg file with quality level 25.
   && using an encoder object based on the guid
   && for the quality parameter category.
   myencoderparameter = .imaging.encoderparameter.new(.imaging.encoder.quality, 25)
param.add = myencoderparameter
save("c:\myjpeg_025.jpg", .imaging.imageformat.jpeg, myencoderparameters)





After all those posts discussing and showing how to create gradient backgrounds for vfp forms, I finally decided to create a simple but powerful class to ease this process.

The GradBackgrounds class is stored inside the gradientobjects.vcx, the class that was published last year that converts any commandbutton, graphical checkbox or graphical optionbox.

Just drop an instance of the class gradbackgrounds to any form, container or pageframe and set some properties to obtain the gradient effects shown below.

All the background images are created using gdi+, but with no helper class, because I wanted to obtain the best performance possible.



gradientmode - numeric, from 1 to 4, determines the gradient type to be created
1 - horizontal   2 - vertical   3 - diagonal 1   4 - diagonal 2 using linear gradient
brushes with 2 colors

backcolor1 - numeric, the rgb value of the starting color of the gradient background

backcolor2 - numeric, the rgb value of the destination color of the gradient background

reducecolorlevel - numeric, automatically sets the destination color of the gradient (backcolor2) ranging from 0 (no change) to 100 (white). if left to .f., then no change is applied and the original values of backcolor2 and selbackcolor2 will be used.

updatetabcolor - in the case of a pageframe, sets "themes" off to allow the tab background to be in the same color of the gradient

update - updates the gradient if you change any of the above properties


form using gradientmode = 1



form using gradientmode = 2



form using gradientmode = 3



form using gradientmode = 4



playing with pageframes

As containers, pageframes allow to set a picture property. we can also obtain a cool effect changing the tab colors to use the same color of the gradient picture.

To make it work, drop an instance of the class inside every page thet you want to convert to gradient. when inside a pageframe, the property gradient mode becomes automatic, and works according to the 'tabOrientation' property of the pageframe.




The gradient adapts to the "taborientation" property of the pageframe




important notes

To make the class work inside a container, don't forget to set its backstyle to 1 - opaque
Don't forget to set the backstyle property of your labels to 0 - transparent


vfp9 is cool !

In this version of the class I started using some scripts to ease the manipulation of the properties. For example, now if you double click on the backcolor1 property, the color picker opens automatically, to allow you to choose your color. thanks to the great book "what's new in nine", and some great tips from Fabio Lunardon and Tamar Granor.



This class is totally free. The information provided on this page and the source code related to this article comes without any warranty whatsoever. use it at your own risk.


some related links

gradient backgrounds in your forms with gdi+

gradient command buttons with gdi+

gradient objects with gdi+ revisited




click here to download the latest version of the gradient objects class.


Extract icons from EXE, DLL and ICO files with GdiPlus-X

Some types of files allow to store various icons together with other binary data, such as exes and dlls. .ICO files also allow to store more than one icon in a single file. Windows uses this a lot, and stores almost all the icons that it uses all the time in some dll or exe libraries.

The GdiplusX library can easily extract these icons, using the function “ExtractAssociatedIcon” from the xfcIcon class, as follows:


All samples below use the Gdiplus-X library from VFP-X project. Download the latest stable release from codeplex:




* the following code example demonstrates how to extract icons from an exe file
do locfile("system.app")

local lcfile, lnindex
local loicon as
local lobmp as
lcfile =
&& _vfp.servername
lnindex = 0
with _screen.system
   do while
      loicon = .
.extractassociatedicon(lcfile, lnindex)
      if isnull
      lcNewfile = "c:\" + justfname(lcfile) + transform
(lnindex) + ".png"
      lobmp = loicon.tobitmap()
(lcnewfile, .imaging.imageformat.png)
      lnindex = lnindex + 1

The file extracticons.scx in the samples folder brings a form that permits you to select any file, and GdiplusX will draw all associated icons inside an imagecanvas object, like in the picture below:

need more icons ?

In my tests, after I created this function, I was very curious about what icons my computer could be storing inside so many executables and dlls installed, so I created a simple program that will scan through a selected directory, and does a recursive search in all of its subfolders, looking for all the files that can possibly store icons.

To my surprise, lots, really thousands of icons emerged... and very interesting results, I ensure you !

You can try this in your computer too.

Save the program below as howto_extracticonsfromdir2.prg in the help folder of the library. It uses a very cool routine from michael reynolds, that he kindly published in www.fox.wikis.com to obtain the names of all files from the subdirectories. Please note that this will consume some big efforts from your machine, so be prepared to wait about a minute till this task is finished. after running this sample, all the icons will be stored in “c:\myicons\”.

* file : howto_extracticonsfromdir2.prg
* author : VFPIMAGING
* save this file in the help directory in the gdiplus-x library folder
* the following code performs the following actions:
* asks the user for a path
* creates a cursor containing all available file names (exe, dll and ico)
* from the selected and its subfolders
* scans the cursor and extract all associated icons from each file

* init gdi+
do locfile("system.app")
* create destination directory to receive the extracted icons
lcdir = "c:\myicons\"
if not directory(lcdir)
   mkdir (lcdir)
* create the cursor that will store the valid file locations
create cursor recursive (cfile c(250))

local lccurdrive, lccurdir, lcselecteddir
lccurdrive =
lccurdir =
lcselecteddir =
if empty(lcselecteddir)
   wait window "invalid directory"
   return .f.

wait window "retrieving folders information" nowait

* scan through the selected and the subfolders
chdir &lccurdrive.&lccurdir.
* browse

with _screen.system.drawing
local lcfile, lnindex, lntotrec
local lnoldpercentage, lnpercentage
local loicon as xfcicon
local lobmp as xfcbitmap
store 0 to lnpercentage, lnoldpercentage
lntotrec =
lcfile = recursive.cfile
lnindex = 0
do while .t.
loicon =
* extract the associated icon
loicon = .icon.extractassociatedicon(lcfile, lnindex)
if isnull(loicon)
lcnewfile = lcdir + justfname(lcfile) + transform(lnindex) + ".png"
lobmp =
* send the icon to a gdi+ bitmap object
lobmp = loicon.tobitmap()
if vartype(lobmp) <> "o"
* save the bitmap as png
lobmp.save(lcnewfile, .imaging.imageformat.png)
lnindex = lnindex + 1
* show progression
lnrec = recno()
lnpercentage =
round((lnrec / lntotrec),1)
if lnpercentage > lnoldpercentage
wait window "extracting icons from files..." + chr(13) + ;
"elapsed: " +
transform(lnpercentage * 100) + " %" nowait
lnoldpercentage = lnpercentage

* function : recurse
* author : michael reynolds
* description : good for performing file processing throughout an entire directory tree.
* the function, recurse(), is called with the full path of a directory.
* recurse() will then read all files and directories in the path.
* a function can be called to process files that it finds.
* plus, the function calls itself to process any sub-directories.
function recurse(pcdir)
local lnptr, lnfilecount, lafilelist, lcdir, lcfile
chdir (pcdir)
dimension lafilelist[1]
*--- read the chosen directory.
lnfilecount = adir(lafilelist, '*.*', 'd')
for lnptr = 1 to lnfilecount
if 'd' $ lafilelist[lnptr, 5]
*--- get directory name.
lcdir = lafilelist[lnptr, 1]
*--- ignore current and parent directory pointers.
if lcdir != '.' and lcdir != '..'
*--- call this routine again.
*--- get the file name.
lcfile = lower(fullpath(lafilelist[lnptr, 1]))
*--- insert into cursor if .exe, .ico or .dll
if inlist(lower(justext(lcfile)),"dll","exe","ico")
insert into recursive (cfile) values (lcfile)
*--- move back to parent directory.
chdir ..



The above procedure shows how to extract the associated icons from some files. Before using those icons in your applications, you first need to make sure you have the rights to do that. Read carefully the eula from those applications prior to using them !


I hope you enjoy !



After some requests, I'm sending a new version of GPIMAGE2, an adapted class from the original GpImage class from Alexander Golovlev.

This new version adds 3 new features to the previous version:
Control smoothing mode, Interpolation mode and a Gradient brush.

Gdi+ originally offers 6 kinds of linear gradient brushes, and many possibilities for path gradient brushes, but to update Gpimage2 is not a priority any more because the GdiplusX library brings much more value, and is compatible with the .NET "System.Drawing" namespace.

So, if you still didn't upgrade to VFP9, you can download this new version, and play with some gradients.

I've included 3 samples that create gradients. you'll find them in the "examples" folder.

brushesgradient.prg   creates some shapes using gradients
gradientform.scx   creates a sample form with gradient effect
gradientform2.scx   creates a sample form with gradient effect, allowing to change the colors and the gradient direction duruing execution

Another new sample, smoothing.scx, from Rafael Lippert, demonstrates how to control the smoothing mode if images.

Enjoy !

GPIMAGE2 gdi+ class



Recently, MSDN added a new and very useful feature to the .net development site, the msdn community content. According to them, "msdn community content provides an infrastructure for users to comment, edit, and add content to the visual studio 2005 and .net framework 2.0 online documentation. (...) anyone can register for the site by signing in with a microsoft passport or windows live id and agreeing to the site terms of use and the participant code of conduct.  anyone who is registered and signed in to the site can create new community content and edit existing community content."

Currently, MSDN provides many sample codes for .net, c#, c++ and j# users. from now on, we hope to add VFP too !

As the new gdiplusx library mimics the "system.drawing" namespace from .net. that means that we can convert codes created for vb .net to vfp very easily. so, i started posting some VFP codes at the "community content" part of some topics.

Have a look at the links below and tell me what you think.


Well, better that that, would be if YAG or Milind Lele convinced MSDN people to keep some specific room for some VFP codes for Gdiplus-X directly there :-)