2006-02-22

SPECIAL EFFECTS ON IMAGES WITH GDI+ Part 2

The information contained in this article is deprecated. Please refer to the articles published in UTMAG, on the same subject, using the GdiPlusX classes, that are more suitable to applying effects to images for VFP developers:

Special effects on images with new GDIPlus-X classes - Part 1
Special effects on images with new GDIPlus-X classes - Part 2

 

This is the continuation of my previous post. to completely understand the contents of this one, i strongly recommend you to read first that article.

http://weblogs.foxite.com/vfpimaging/archive/2006/02/13/1139.aspx

The ImageAttributes class has many other methods, that can produce some really cool effects. in this post i'll show some other things we can do with the class.

One common task when working with images is to "draw" an image over another, something such as a company logo in the bottom of an image, or to "draw" this logo as a watermark.

The most simple approach would be to load the source image, load the graphics class for that image, load the logo image, and draw it over the main image.

In the next examples i'll borrow some of craig boyd's vfp logos, that you can find at his blog: “creating our own fox logos”. maybe you find them a little bit scary, but they'll fit perfectly for the next examples.

http://www.sweetpotatosoftware.com/spsblog/permalink,guid,55eed756-353c-4086-9a2e-7c52ac926611.aspx



Our code would be something like this :

*!* program : simpledrawimage
*!* author  : VFPIMAGING
*!* Draw a small image over a big image


if not "gpattrib" $ set("procedure")
   set procedure to gpattrib additive
endif


lcsource = getpict()
lclogo   = getpict()
lcdestination = addbs(justpath(lcsource))+ "drawimage_" +;
      juststem(lcsource)+".bmp"
local lologo as gpimage of ffc/_gdiplus.vcx
lologo = newobject('gpimage',home() + 'ffc/_gdiplus.vcx')
lologo.createfromfile(lclogo)
local loimage as gpimage of ffc/_gdiplus.vcx
loimage = newobject('gpimage',home() + 'ffc/_gdiplus.vcx')
loimage.createfromfile(lcsource)
local lographics as gpgraphics of ffc/_gdiplus.vcx
lographics = newobject('gpgraphics',home() + 'ffc/_gdiplus.vcx')
lographics.createfromimage(loimage)
lographics.drawimageat(lologo, loimage.imagewidth - lologo.imagewidth, ;
loimage.imageheight - lologo.imageheight)
loimage.savetofile(lcdestination, "image/bmp")
return




Sounds ugly !
What about applying a colormatrix in order to make the logo image 50% transparent?
To do that, we'll use the concepts discussed in my previous post.

*!* program : transparencies
*!* author  : VFPIMAGING
*!* Applying Image Attributes with Color matrix
if not "gpattrib" $ set("procedure")
   set procedure to gpattrib additive
endif
lcsource = getpict()
lclogo   = getpict()
lcdestination = addbs(justpath(lcsource))+ "transp_" +;
      juststem(lcsource)+".bmp"


*!* applying transparency to logo
local lologo as gpimage of ffc/_gdiplus.vcx
local loatt  as gpattrib
local lcmatrix as colormatrix
lologo = newobject('gpimage',home() + 'ffc/_gdiplus.vcx')
lologo.createfromfile(lclogo)
wlogo = lologo.imagewidth
hlogo = lologo.imageheight
lcmatrix = colormatrix(;
      1, 0, 0, 0, 0, ;
      0, 1, 0, 0, 0, ;
      0, 0, 1, 0, 0, ;
      0, 0, 0, 0.5, 0, ;
      0, 0, 0, 0, 1)
loatt = createobject("gpattrib")
loatt.setcolormatrix(lcmatrix)
local loimage as gpimage of ffc/_gdiplus.vcx
loimage = newobject('gpimage',home() + 'ffc/_gdiplus.vcx')
loimage.createfromfile(lcsource)
wimg = loimage.imagewidth
himg = loimage.imageheight
local lographics as gpgraphics of ffc/_gdiplus.vcx
lographics = newobject('gpgraphics',home() + 'ffc/_gdiplus.vcx')
lographics.createfromimage(loimage)
local ologobounds as gprectangle of home() + ffc/_gdiplus.vcx
ologobounds = newobject('gprectangle',home()+'ffc/_gdiplus.vcx','', 0, 0, wlogo, hlogo)
local odestlogobounds as gprectangle of home() + ffc/_gdiplus.vcx
odestlogo = newobject('gprectangle',home()+'ffc/_gdiplus.vcx')
odestlogo.x = wimg - wlogo
odestlogo.y = himg - hlogo
odestlogo.w = wlogo
odestlogo.h = hlogo
lographics.drawimageat(lologo, 0, loimage.imageheight - lologo.imageheight)


*!* drawimageportionscaled method
*!* draws portion of an image at the specified location and with the specified size.
*!* syntax: this.drawimageportionscaled(toimage, destrectangle,srcrectangle[, srcunit[, imageattribs]])
*!* return values: logical, representing success or failure.
*!* parameters:
*!* toimage - required, gpimage object to draw.
*!* destrectangle - required, a gprectangle object specifying destination location.
*!* srcrectangle - required, a gprectangle object specifying the portion of image to draw.
*!* srcunit - optional, unit of measure for source image, defined in gdiplus_unit_* constants
*!* imageattribs - optional, integer gdi+ handle imageattributes object


lographics.drawimageportionscaled(lologo, odestlogo, ologobounds, 2, loatt)
loimage.savetofile(lcdestination, "image/bmp")
return




The result isn’t that cool, because of the white background of the logo.
Can we do better that that ?
 
We can use another imageattributes function, remaptable. again, you can find on msdn great information about that method:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdicpp/gdiplus/gdiplusreference/classes/imageattributesclass/imageattributesmethods/clone_98.asp

Applying this function, we can change every white opaque (alpha = 255) pixel of the logo to white transparent (alpha = 0). this way, we can “draw” only the internal part of the logo image, just the fox, without the white background. we need to pass as parameters the original color, original alpha, new color and new alpha. during rendering, any color that matches one of the old colors in the remap table is changed to the corresponding new color.

The main picture used is from fernando de noronha, one of the brazilian most beautiful sites. interested ? check this link for more pictures ! great place to dive, all kinds of fish, dolphins, turtles. high temperatures, and the most beautiful beaches of my country.

http://baixaki.ig.com.br/buscawall.asp?papel=fernando+de+noronha&page=1&tipo=

The code below is responsible for the image presented, and is divided in 4 parts :

1 – top left
draw the logo with its original attributes

2 – top right
draw the logo applying a colormatrix to set transparency to 50%

3 – bottom left
draw the logo applying a “remaptable”, changing every white opaque (alpha = 255) pixel of the logo to white transparent (alpha = 0).
the rest of the image is pasted without applying a colormatrix, without transparency.

4 – bottom right
same as previous example, but applying a colormatrix to set the opacity to 50%

Save all the code below as imgattapply.prg and execute it to have this result :



*!* program : imgattapply.prg
*!* author  : VFPIMAGING
*!* applying imageattributes

#define unitworld      0
#define unitdisplay    1
#define unitpixel      2
#define unitpoint      3
#define unitinch       4
#define unitdocument   5
#define unitmillimeter 6
if not "gpattrib" $ set("procedure")
   set procedure to gpattrib additive
endif
lcsource = getpict()
lclogo   = getpict()
lcdestination = addbs(justpath(lcsource))+ "r_" +;
      juststem(lcsource)+".bmp"


local lologo as gpimage of ffc/_gdiplus.vcx
lologo = newobject('gpimage',home() + 'ffc/_gdiplus.vcx')
lologo.createfromfile(lclogo)
wlogo = lologo.imagewidth
hlogo = lologo.imageheight


*!* create a rectangle object with the logo origunal bounds
*!* this object will be used to draw the logo to the image
*!* as a parameter
local ologobounds as gprectangle of home() + ffc/_gdiplus.vcx
ologobounds = newobject('gprectangle',home()+'ffc/_gdiplus.vcx','', 0, 0, wlogo, hlogo)
local loimage as gpimage of ffc/_gdiplus.vcx
loimage = newobject('gpimage',home() + 'ffc/_gdiplus.vcx')
loimage.createfromfile(lcsource)
wimg = loimage.imagewidth
himg = loimage.imageheight
local lographics as gpgraphics of ffc/_gdiplus.vcx
lographics = newobject('gpgraphics',home() + 'ffc/_gdiplus.vcx')
lographics.createfromimage(loimage)
local loatt as gpattrib
loatt = createobject("gpattrib")


*!* example 1
*!* original image
*!* position : top left
*!* the method drawimageat does not apply
imageattributes
lographics.drawimageat(lologo, 0, 0)


*!* example 2
*!* image with 50% transparency
*!* position : top right
*!* the position (4,4) of the matrix is responsible for the opacity
local lcmatrix as colormatrix
lcmatrix = colormatrix(;
      1, 0, 0, 0, 0, ;
      0, 1, 0, 0, 0, ;
      0, 0, 1, 0, 0, ;
      0, 0, 0, 0.5, 0, ;
      0, 0, 0, 0, 1)
loatt.setcolormatrix(lcmatrix)


*!* create rectangle object with the position of the transformed image to draw
local odestlogo2 as gprectangle of home() + ffc/_gdiplus.vcx
odestlogo2 = newobject('gprectangle',home()+'ffc/_gdiplus.vcx')
odestlogo2.x = wimg - wlogo
odestlogo2.y = 0
odestlogo2.w = wlogo
odestlogo2.h = hlogo
*!* now we can draw the image
*!* to apply the imageattributes object, we need to use
*!* drawimageportionscaled from gpgraphics
lographics.drawimageportionscaled(lologo, odestlogo2, ologobounds, unitpixel, loatt)
*!* clear the colormatrix for the next example
loatt.clearcolormatrix()


*!* example 3
*!* logo image with no transparency
*!* remaptable of colors from logo image
*!* convert white with alpha 255 (opaque) to white transparent alpha (0)
*!* position : bottom left
*!* remaptable(tnoldcolor, tnnewcolor, tnoldalpha,
tnnewalpha)
loatt.remaptable(rgb(255,255,255),rgb(255,255,255),255,0)
local odestlogo3 as gprectangle of home() + ffc/_gdiplus.vcx
odestlogo3 = newobject('gprectangle',home()+'ffc/_gdiplus.vcx')
odestlogo3.x = 0
odestlogo3.y = himg - hlogo
odestlogo3.w = wlogo
odestlogo3.h = hlogo
lographics.drawimageportionscaled(lologo, odestlogo3, ologobounds, unitpixel, loatt)
loatt.clearremaptable()


*!* example 4
*!* image with 50% transparency using colormatrix
*!* remaptable of colors from logo image
*!* convert white with alpha 255 (opaque) to white transparent alpha (0)
*!* position : bottom right
*!* remaptable(tnoldcolor, tnnewcolor, tnoldalpha, tnnewalpha)
loatt.remaptable(rgb(255,255,255),rgb(255,255,255),255,0)
local lcmatrix as colormatrix
lcmatrix = colormatrix(;
1, 0, 0, 0, 0, ;
0, 1, 0, 0, 0, ;
0, 0, 1, 0, 0, ;
0, 0, 0, 0.5, 0, ;
0, 0, 0, 0, 1)
loatt.setcolormatrix(lcmatrix)
local odestlogo4 as gprectangle of home() + ffc/_gdiplus.vcx
odestlogo4 = newobject('gprectangle',home()+'ffc/_gdiplus.vcx')
odestlogo4.x = wimg - wlogo
odestlogo4.y = himg - hlogo
odestlogo4.w = wlogo
odestlogo4.h = hlogo
lographics.drawimageportionscaled(lologo, odestlogo4, ologobounds, unitpixel, loatt)


*!* save the image with the 4 logos
loimage.savetofile(lcdestination, "image/bmp")


return

*!* drawimageportionscaled method
*!* draws portion of an image at the specified location and with the specified size.
*!* syntax: this.drawimageportionscaled(toimage, destrectangle,srcrectangle[, srcunit[, imageattribs]])
*!* return values: logical, representing success or failure.
*!* parameters:
*!* toimage - required, gpimage object to draw.
*!* destrectangle - required, a gprectangle object specifying destination location.
*!* srcrectangle - required, a gprectangle object specifying the portion of image to draw.
*!* srcunit - optional, unit of measure for source image, defined in gdiplus_unit_* constants
*!* imageattribs - optional, integer gdi+ handle imageattributes object


There are still many other interesting things to be done with imageattributes.
I’ll be showing some other functions of this class in my next posts.

The form NEWMATRICES.scx was updated, now I've included a hue colormatrix, hope you enjoy !

You can download GpAttrib from here. http://weblogs.foxite.com/vfpimaging/files/2006/02/gpattrib.zip

2006-02-13

SPECIAL EFFECTS ON IMAGES WITH GDI+

The information contained in this article is deprecated. Please refer to the articles published in UTMAG, on the same subject, using the GdiPlusX classes, that are more suitable to applying effects to images for VFP developers:

Special effects on images with new GDIPlus-X classes - Part 1
Special effects on images with new GDIPlus-X classes - Part 2

 

Sometimes we may need to make some adjustments in the colors of an image, like to make gamma adjustments, change saturation, contrast, brightness, hue, convert to grayscale, to increase or decrease a specific color, etc.

The most simple way to do that would be to "read" every single pixel of the image, extract the 4 integer argb values (alpha, red, green and blue), apply the adjustments to the color and then "redraw" every pixel.

The code below is based on bob powell's example from http://www.bobpowell.net/grayscale.htm , and shows us how we can convert an image to greyscale pixel by pixel. i strongly recommend you read the topic above, where you can find some other interesting examples about using gdi+.

 

The effective luminance of a pixel is calculated with the following formula: c = 0.3 red + 0.59 green + 0.11 blue
This luminance value can then be turned into a grayscale pixel using color.argb(c,c,c).

 



 

*!* Program : grayscale1
*!* Author  : VFPIMAGING
*!* Based on example from
http://www.bobpowell.net/grayscale.htm

lcsource = getpict()
lcdestination = addbs(justpath(lcsource))+ "grey_" +;
   juststem(lcsource)+".bmp"
local lobitmap as gpbitmap of ffc/_gdiplus.vcx

lobitmap = newobject("gpbitmap", home() + "ffc/_gdiplus.vcx")
lobitmap.createfromfile(lcsource)

local locolor as gpcolor of ffc/_gdiplus.vcx
locolor = newobject("gpcolor", home() + "ffc/_gdiplus.vcx")

local x, y, lnsourcecolor, lnluma
for y = 0 to lobitmap.imageheight - 1
   
for x = 0 to lobitmap.imagewidth - 1
       
lnsourcecolor = lobitmap.getpixel(x,y)
        locolor.init(lnsourcecolor)
       
lnluma = int(locolor.red * 0.3 + locolor.green * 0.59 + ;
        locolor.blue * 0.11)
        locolor.set(lnluma,lnluma,lnluma)
        lobitmap.setpixel(x,y,locolor.argb)
    next
next

loBitmap.SaveToFile(lcDestination, "image/jpeg", "quality=100")
return


 

It uses the technique of extracting each pixel colour, and redraws with the average between the 3 components (red, green and blue). according to bob powell, http://www.bobpowell.net/grayscale.htm "this isn't really a good example of how it should be done in a production situation but it does show the principles involved clearly".

 

But gdiplus brings us with the possibilities to apply such kind of big changes to image colors in a really fast way. but to do that, we need to use the imageattributes class. according to microsoft, "an imageattributes object contains information about how bitmap and metafile colors are manipulated during rendering. an imageattributes object maintains several color-adjustment settings, including color-adjustment matrices, grayscale-adjustment matrices, gamma-correction values, color-map tables, and color-threshold values."

Unfortunately, this class was not added to _gdiplus.vcx that came with vfp9. to make things easier, i've created a wrapper class to work with it, doing the needed api calls do gdiplus.dll.

Many people still did not move to vfp9. to these people, it's possible to work with gdi+, using alexander golovlev's GpImage2, a wrapper class created in 2003 originally published in ut. under the author's authorization i've added some functions that were missing to it, and it can be downloaded from http://sites.google.com/site/gpimage2/ , where you can see some samples of what can be done with the class. works with vfp7 and above. may work with vfp6 too, but have not tested yet.

My wrapper class that will deal with imageattributes, gpattributes can work with both _gdiplus.vcx and with GpImage2. if you already own vfp9, i recommend the use of _gdiplus.vcx.

The examples below will deal with vfp9 _gdiplus.vcx. gpimage users will see the equivalent code in the download at the end of this post. the principles are exactly the same. _gdiplus.vcx and gpimage.prg have just some different sintaxes.

Although ms did not gift us with a complete gdi+ wrapper class, there's great information about it on msdn, most of them directed to .net and c users. the way the class works with other languages is almost the same. most of the examples can be really easily translated, and there's very good information about how gdi+ works. i am not an expert of imageattributes, all i know i've learned from msdn and some other great forums. at the end of this post i'll show you my preferred links.

Lets see how it can help us.

The code below will produce exactly the same result as the code presented before. just make sure that gpattributes is in your classlib or path.


*!* program : grayscale2
*!* author  : VFPIMAGING
*!* applying Image Attributes with Color matrix


if not "gpattrib" $ set("procedure")
  
set procedure to gpattrib additive
endif

lcsource = getpict()
lcdestination = addbs(justpath(lcsource))+ "grey2_" +;
    juststem(lcsource)+".bmp"

local loimage as gpimage of ffc/_gdiplus.vcx
local loatt as gpattrib
local lcmatrix as colormatrix

loimage = newobject('gpimage',home()+'ffc/_gdiplus.vcx')
loimage.createfromfile(lcsource)
lcmatrix = colormatrix(;
   
.30, .30, .30, 0, 0, ;
   
.59, .59, .59, 0, 0, ;
   
.11, .11, .11, 0, 0, ;
     0 ,   0,   0, 1, 0, ;
     0 ,   0,   0, 0, 1)

loatt = createobject("gpattrib")
loatt.setcolormatrix(lcmatrix)
loatt.applyimageattribute(loimage.gethandle())
loimage.savetofile(lcdestination, "image/jpeg", "quality=100")

return

 

What I did here was to apply a colormatrix to the image. according to msdn, "a 5x5 color matrix is a homogeneous matrix for a 4-space transformation. the element in the fifth row and fifth column of a 5x5 homogeneous matrix must be 1, and all of the other elements in the fifth column must be 0. color matrices are used to transform color vectors. the first four components of a color vector hold the red, green, blue, and alpha components (in that order) of a color. the fifth component of a color vector is always 1."

I am no expert on colormatrices. fortunately, msdn brings to us some really cool examples. enter www.msdn.com and search for "gdiplus colormatrix".

 
c11 c12 c13 c14 c15 à component r - red

c21 c22 c23 c24 c25 à component g - green

c31 c32 c33 c34 c35 à component b - blue

c41 c42 c43 c44 c45 à component a - alpha (transparency)

c51 c52 c53 c54 c55 à component brightness

 
 

In this 5x5 matrix, i'll classify some important positions :

 

c11 - c22 - c33 - control the contrast of a color

position 11 = red, 22 = green, 33 = blue

1 means no change

0 means to eliminate the component

 

c44 - control of opacity/alpha

 

c51 - c52 - c53 - control the brightness of a component

0 means no change

example : if you put 0.75 in position c51, the red component of each pixel in the image will be increased in 0.75

 


c54 - control the brightness of the opacity/alpha component

0 means no change

 

You can get some very interesting effects applying colormatrices :


Yere are some examples. to see the results, just change the contents of the local variable lcmatrix to these ones :

matrix1 - obtain negative of an image

 

lcmatrix = colormatrix(;

    -1, 0, 0, 0, 0, ;

    0 , -1, 0, 0, 0, ;

    0 , 0, -1, 0, 0, ;

    0 , 0, 0, 1, 0, ;

    1 , 1, 1, 0, 1)

 

matrix2 - obtain just the red components of an image

lcmatrix = colormatrix(;

    1 , 0, 0, 0, 0, ;

    0 , 0, 0, 0, 0, ;

    0 , 0, 0, 0, 0, ;

    0 , 0, 0, 1, 0, ;

    0 , 0, 0, 0, 1)

 

 

matrix3 - obtain just the blue components of an image


lcmatrix = colormatrix(;

    0 , 0, 0, 0, 0, ;

    0 , 0, 0, 0, 0, ;

    0 , 0, 1, 0, 0, ;

    0 , 0, 0, 1, 0, ;

    0 , 0, 0, 0, 1)


 

matrix4 - remove the blue components of an image

 

lcmatrix = colormatrix(;

    1 , 0, 0, 0, 0, ;

    0 , 1, 0, 0, 0, ;

    0 , 0, 0, 0, 0, ;

    0 , 0, 0, 1, 0, ;

    0 , 0, 0, 0, 1)

 

 

matrix5 - scales the blue component of each pixel in the image by a factor of 2

 

lcmatrix = colormatrix(;

    1 , 0, 0, 0, 0, ;

    0 , 1, 0, 0, 0, ;

    0 , 0, 2, 0, 0, ;

    0 , 0, 0, 1, 0, ;

    0 , 0, 0, 0, 1)

 

 

matrix6 - adds 0.20 to the red component of each pixel in the image

 

lcmatrix = colormatrix(;

       1 , 0, 0, 0, 0, ;

       0 , 1, 0, 0, 0, ;

       0 , 0, 1, 0, 0, ;

       0 , 0, 0, 1, 0, ;

    0.20 , 0, 0, 0, 1)

 

 

You'll find some very interesting information on these links from msdn:

 

using a color matrix to transform a single color

translating colors

scaling colors

rotating colors

shearing colors

 

Changing gamma

We can also change the gamma of an image directly, with no need of specific colormatrices:



*!* program : gamma
*!* author : VFPIMAGING
*!* applying imageattributes with colormatrix
if not "gpattrib" $ set("procedure")
   set procedure to gpattrib additive
endif
lcsource = getpict()
lcdestination = addbs(justpath(lcsource))+ "grey2_" +;
    juststem(lcsource)+".bmp"
local loimage as gpimage of ffc/_gdiplus.vcx
local loatt as gpattrib
local lcmatrix as colormatrix
loimage = newobject('gpimage',home()+'ffc/_gdiplus.vcx')
loimage.createfromfile(lcsource)
lcmatrix = colormatrix(;
    1, 0, 0, 0, 0, ;
    0, 1, 0, 0, 0, ;
    0, 0, 1, 0, 0, ;
    0, 0, 0, 1, 0, ;
    0, 0, 0, 0, 1) && this matrix has no effect
loatt = createobject("gpattrib")
loatt.setcolormatrix(lcmatrix)
g = 2 && gamma value chosen
loatt.setgamma(g)
&& we set the gamma directly, no need of specific colormatrices
loatt.applyimageattribute(loimage.gethandle())
loimage.savetofile(lcdestination, "image/jpeg", "quality=100")



Applying more than one colormatrix


Sometimes we may need to apply more than one colormatrix to an image. we can of course apply one and the other next, but this will take much more time of process. We can reduce it drastically if we create another colormatrix with the result of the multiplication of all matrices needed. we need to multiply 2 at a time.

To make this matrices multiplication, i also added a function to do that, MultiplyColorMatrix(), included in gpattrib library.

*!* brightness increase of 20%
b = 0.20
lcmbright = colormatrix(;
    1, 0, 0, 0, 0, ;
    0, 1, 0, 0, 0, ;
    0, 0, 1, 0, 0, ;
    0, 0, 0, 1, 0, ;
    b, b, b, 0, 1)


*!* contrast decrease of 20%
c = 0.80
lcmcontrast = colormatrix(;
    c, 0, 0, 0, 0, ;
    0, c, 0, 0, 0, ;
    0, 0, c, 0, 0, ;
    0, 0, 0, 1, 0, ;
    0, 0, 0, 0, 1)


*!* we need to create a new colormatrix containing information from all matrices
lcmatrix = multiplycolormatrix(lcmbright,lcmcontrast)


*!* all is needed now is to apply the new matrix created to the image

Controlling colors, contrast, saturation, gamma

In this zip file you'll find an interesting example, that applies some colormatrices to images, run newmatrices.scx

 

 

You can download gpattrib from here.

http://weblogs.foxite.com/vfpimaging/files/2006/02/gpattrib.zip

 

What next ?

There are many other interesting effects that we can apply with Color matrices. on my next posts, I'll try to show some more.

There's already a continuation of this article, that you can access it from here.

http://weblogs.foxite.com/vfpimaging/archive/2006/02/22/1227.aspx

2006-02-09

SCALE AND SHEAR WITH GDI+

Execute the code below to change shear and scale of an image.

Special thanks to Anatolyi Mogylevets, from www.news2news.com
A great part of this code comes from him, once _GdiPlus.vcx is incomplete, what obliges us to call directly through API http://www.news2news.com/vfp/?example=479

 

To better understand how scale and shear work with GDI+, take a look at these links as well:
http://www.vbaccelerator.com/home/vb/code/vbmedia/using_gdi_plus/scale__rotate__skew_and_transform_images/article.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdicpp/gdiplus/gdiplusreference/classes/matrixclass/matrixmethods/shear.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdicpp/gdiplus/gdiplusreference/classes/matrixclass/matrixmethods/shear.asp





 

* Scale and Shear with GDI+
* -------------------------- * special thanks to Anatolyi Mogylevets, from www.news2news.com * a great part of this code comes from him, once _gdiplus.vcx * is still incomplete what obliges us to call directly through Win32Api * http://www.news2news.com/vfp/?example=479 declare integer gdipcreatematrix in gdiplus integer @matrix declare integer gdipdeletematrix in gdiplus integer matrix declare integer gdipshearmatrix in gdiplus; integer matrix, single shearx, single sheary, integer ord declare integer gdipscalematrix in gdiplus; integer matrix, single scalex, single scaley, integer ord declare integer gdipsetworldtransform in gdiplus; integer graphics, integer matrix lcSource = GETPICT("jpg;gif;bmp") lcDestination = addbs(justpath(lcSource))+ "sheared_" +; juststem(lcSource)+".jpg" local loImage as gpimage of _gdiplus.vcx loImage = newobject("gpimage", home() + "ffc/_gdiplus.vcx") loImage.createfromfile(lcsource) local loBitmap as gpbitmap of _gdiplus.vcx loBitmap = newobject("gpbitmap", home() + "ffc/_gdiplus.vcx") local lographics as gpgraphics of _gdiplus.vcx loGraphics = Newobject('gpgraphics',home() + "ffc/_gdiplus.vcx") *** now we create a new image with *** create method - creates a bitmap object. *** syntax: ? this.create(tnwidth, tnheight[, tnpixelformat]) *** tnpixelformat, optional, one of gdiplus_pixelformat_* constants, *** defaults to gdiplus_pixelformat_32bppargb. local lnWidth, lnHeight, lnPixelFormat lnWidth = loimage.imagewidth lnHeight = loimage.imagewidth lnPixelFormat = loImage.PixelFormat local matrix1, xScaleFactor, yScaleFactor, xShearFactor, yShearFactor xScaleFactor = 1.30 yScaleFactor = 0.75 xShearFactor = 0.20 yShearFactor = 0.10 store 0 to matrix1 lnNewWidth = lnWidth * xScaleFactor * (1 + xShearFactor) lnNewHeight = lnHeight * yScaleFactor * (1 + yShearFactor) loBitmap.Create(lnNewWidth, lnNewHeight, lnPixelFormat) loGraphics.Createfromimage(loBitmap) * Create matrix object * and apply scale and shear transformations = gdipCreateMatrix(@matrix1) = gdipScaleMatrix(matrix1, xscalefactor, yscalefactor, 0) = gdipShearMatrix(matrix1, xshearfactor, yshearfactor, 0) = gdipSetWorldTransform(lographics.gethandle(), matrix1) lographics.DrawImageAt(loimage, 0, 0) lographics.ResetTransform() = gdipdeletematrix(matrix1) loBitmap.SavetoFile(lcDestination, "image/jpeg")

2006-02-07

CONVERT IMAGE TYPES WITH VFP9 AND GDI+

The following piece of code loads an image and saves it on the same original folder in the formats supported by GDI+, using the _gdiPlus.vcx class, that you can find in the VFP9 FFC folder:


LOCAL lcSource, lcDestination
m.lcSource = GETPICT()
m.lcDestination = JUSTPATH(m.lcSource) + "\_" + JUSTSTEM(m.lcSource)

LOCAL loImage AS gpimage OF HOME() + ffc / _gdiplus.vcx
m.loImage = NEWOBJECT("gpimage", HOME() + "ffc/_gdiplus.vcx")
m.loImage.CreateFromFile(m.lcSource)
m.loImage.SaveToFile(m.lcDestination + ".jpg","image/jpeg")
m.loImage.SaveToFile(m.lcDestination + ".bmp","image/bmp")
m.loImage.SaveToFile(m.lcDestination + ".tif","image/tiff")
m.loImage.SaveToFile(m.lcDestination + ".gif","image/gif")
m.loImage.SaveToFile(m.lcDestination + ".png","image/png")

*!* jpegs allow to choose the quality of the image
m.loImage.SaveToFile(m.lcDestination + ".jpg","image/jpeg", "quality=70")

ROTATE / FLIP IMAGES WITH VFP9 AND GDI+

Rotating and / or flipping images is a simple task for GDI+. To see the different results possible, change the constant value in the parameter "rotateflip" in the code below.

*-- RotateFlipType constants
#DEFINE RotateNoneFlipNone 0
#DEFINE Rotate90FlipNone   1
#DEFINE Rotate180FlipNone  2
#DEFINE Rotate270FlipNone  3
#DEFINE RotateNoneFlipx    4
#DEFINE Rotate90Flipx      5
#DEFINE Rotate180Flipx     6
#DEFINE Rotate270Flipx     7

LOCAL lcSource, lcDestination
m.lcSource = GETPICT("jpg;gif;bmp")

LOCAL loImage AS gpImage OF FFC / _GdiPlus.vcx
m.loImage = NEWOBJECT("gpimage",HOME() + "ffc/_gdiplus.vcx")
m.loImage.CreateFromFile(m.lcSource)

m.loImage.ROTATEFLIP(Rotate180FlipNone) && try changing using the constants above
m.loImage.SaveToFile("Flipped.png","image/png")

RUN /N Explorer.EXE Flipped.Png





RotateNoneFlipNone 0  

 

Rotate90FlipNone   1  

 

Rotate180FlipNone  2  

 

Rotate270FlipNone  3  



RotateNoneFlipX    4   



Rotate90FlipX      5  

 

Rotate180FlipX     6   



Rotate270FlipX     7   


2006-02-06

RESIZE IMAGES WITH VFP9 and GDI+

The function GetThumbnailImage can be used to get a resized image, but the result may come with less quality.

The sample below does the same thing, but creates an image with a better quality.

#DEFINE GdiPlus_PixelFormat_1BPPindexed      0x00030101
#DEFINE GdiPlus_PixelFormat_4BPPindexed      0x00030402
#DEFINE GdiPlus_PixelFormat_8BPPindexed      0x00030803
#DEFINE GdiPlus_PixelFormat_16BPPgrayscale   0x00101004
#DEFINE GdiPlus_PixelFormat_16BPPRGB555      0x00021005
#DEFINE GdiPlus_PixelFormat_16BPPRGB565      0x00021006
#DEFINE GdiPlus_PixelFormat_16BPPARGB1555    0x00061007
#DEFINE GdiPlus_PixelFormat_24BPPRGB         0x00021808
#DEFINE GdiPlus_PixelFormat_32BPPRGB         0x00022009
#DEFINE GdiPlus_PixelFormat_32BPPARGB        0x0026200a
#DEFINE GdiPlus_PixelFormat_32BPPpARGB       0x000e200b
#DEFINE GdiPlus_PixelFormat_48BPPRGB         0x0010300c
#DEFINE GdiPlus_PixelFormat_64BPPpARGB       0x001c400e

LOCAL lcSource, lcDestination
m.lcSource = GETPICT("jpg;gif;bmp")
m.lcDestination = ADDBS(JUSTPATH(m.lcSource)) + "resized_" + JUSTSTEM(m.lcSource) + ".bmp"

LOCAL loImage AS gpImage OF ffc / _GdiPlus.vcx
m.loImage = NEWOBJECT("gpimage", HOME() + "ffc/_GdiPlus.vcx")
m.loImage.CreateFromFile(m.lcSource)

LOCAL loBitmap AS gpBitmap OF ffc / _GdiPlus.vcx
m.loBitmap = NEWOBJECT("gpbitmap", HOME() + "ffc/_GdiPlus.vcx")

LOCAL loGraphics AS gpGraphics OF HOME() + ffc / _GdiPlus.vcx
m.loGraphics = NEWOBJECT('gpgraphics',HOME() + 'ffc/_GdiPlus.vcx')

*** now we create a new image with
*** create method - creates a bitmap object.
*** syntax: ? this.create(tnwidth, tnheight[, tnpixelFormat])
*** tnpixelFormat, optional, one of GdiPlus_pixelFormat_* constants,
*** defaults to GdiPlus_pixelFormat_32BPPARGB.

LOCAL lnNewWidth, lnNewHeight
m.lnNewWidth = 640  && put here the desired width
m.lnNewHeight = 480 && put here the desired height

m.loBitmap.CREATE(m.lnNewWidth, m.lnNewHeight, GdiPlus_PixelFormat_32BPPpARGB)
*** the other constants are in the beginning of this code

m.loGraphics.CreateFromImage(m.loBitmap)
m.loGraphics.DrawImageScaled(m.loImage, 0, 0, m.lnNewWidth, m.lnNewHeight)
m.loBitmap.SaveToFile(m.lcDestination, "image/bmp")

RETURN
 

Update 04/08/2007

 

Below is another way to resize an image using the GetThumbnailImage function, shown by Craig Boyd in a UT thread:

LOCAL lcSource, lcDestination
m.lcSource = GETPICT()
m.lcDestination = "c:\" + JUSTFNAME(m.lcSource) && image will be saved on to c:\</font>
IF ! CreateThumbnail(m.lcSource, m.lcDestination, 85, 100)
    MESSAGEBOX("unable to create image")
ENDIF

FUNCTION CreateThumbnail(tcsource, tcdestination, tnwidth, tnheight)
    LOCAL llSuccess, loImage, loThumbImage
    m.llSuccess = .F.
    IF FILE(m.tcsource)
        m.loImage = NEWOBJECT('gpimage',HOME(1) + 'ffc\_gdiplus.vcx')
        m.loImage.CreateFromFile(m.tcsource)
        m.loThumbImage = m.loImage.getthumbnailimage(m.tnwidth, m.tnheight)
        IF TYPE("lothumbimage") = "o"
            m.llSuccess = m.loThumbImage.SaveToFile(m.tcdestination, "image/jpeg")
        ENDIF
    ENDIF
    RETURN m.llSuccess
ENDFUNC