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

2 comments:

  1. Cesar,


    Absolutely, positively awesome! Thank you for sharing your GDIPLUS techniques with the rest of us!


    Malcolm

    ReplyDelete
  2. You have done some GREAT work with this. It is so close to what I want to do.

    I was looking for a way to create custom shapes that I can fill with colors

    like a car that you could change the color much like you can add a rectangle shape to a form then change the fill color

    ReplyDelete