Blending Two Images Using GDIPlusX
After seeing a post on the Micrsoft forums. I set out to try and solve how to blend two images using GDI+. I could find little information on the web on how to solve this particular problem, so I came up with my own technique (with some excellent help from Craig Boyd).
Here is a sample blended image and the VFP / GDIPlusX code that I used to create it.

Paste this code into a PRG and run it. This code requires the GDIPlusX library from VFPX.
Local lcPict1, lcPict2
m.lcPict1 = Getpict()
If File(m.lcPict1)
m.lcPict2 = Getpict()
If File(m.lcPict2)
ImageAlphaBlend(m.lcPict1, m.lcPict2)
Endif
Endif
**********************************************************
Function ImageAlphaBlend(tcPictLeft, tcPictRight)
**********************************************************
Local loColorMatrix As xfcCOlorMatrix
Local loImageLeft As xfcImage
Local loImageRight As xfcImage
Local loBitmapPart As xfcBitmap
Local loBitmapLeft As xfcBitmap
Local laImageAttribs[1]
Local loGfxLeft As xfcGraphics
Local loGfxPart As xfcGraphics
Local loGfxScreen As xfcGraphics
Local lnAlphaSteps, lnBlendPercentage, lnWidthOpaque, lnStep, lnHeightImage, lnLeftStart
** Sets the number of Alpha blend steps used to render the blend.
** The max is 256. lower steps equals lower quality, but higher speed
m.lnAlphaSteps = 128
** Sets the percentage of the image that is blended
m.lnPercentageBlend = .75
Dimension laImageAttribs[m.lnAlphaSteps]
** Requires the GDIPlusX library (version 1.20 beta)
** http://www.codeplex.com/VFPX/Release/ProjectReleases.aspx?ReleaseId=15083
Do (Locfile("SYSTEM.APP"))
With _Screen.System.Drawing
m.loImageRight = .Image.FromFile(m.tcPictLeft)
m.loImageLeft = .Image.FromFile(m.tcPictRight)
** Force the left image to be the same size as the right image
m.loBitmapLeft = .Bitmap.New(m.loImageRight.Width, m.loImageRight.Height)
m.loGfxLeft=.Graphics.FromImage(m.loBitmapLeft)
m.loGfxLeft.Clear(.Color.Transparent)
m.loGfxLeft.DrawImage(m.loImageLeft,0,0,m.loBitmapLeft.Width,m.loBitmapLeft.Height)
m.lnWidthOpaque = m.loImageRight.Width * (1 - m.lnPercentageBlend) / 2
m.lnWidthPart = Ceiling((m.loBitmapLeft.Width-m.lnWidthOpaque*2)/m.lnAlphaSteps)
m.loBitmapPart = .Bitmap.New(m.lnWidthPart, m.loBitmapLeft.Height)
m.loGfxPart=.Graphics.FromImage(m.loBitmapPart)
m.loGfxPart.Clear(.Color.Transparent)
** Pre-fill ImageAttributes with Alpha ColorMatrix blend for performance
** The biggest advantage to doing this is if you were processing multiple
** set of images at a time, which we aren't doing here.
m.loColorMatrix=.Imaging.ColorMatrix.New()
For m.lnCurrentStep = 1 To m.lnAlphaSteps
laImageAttribs[m.lnCurrentStep] = .Imaging.ImageAttributes.New()
m.loColorMatrix.Matrix33 = m.lnCurrentStep/m.lnAlphaSteps
laImageAttribs[m.lnCurrentStep].SetColorMatrix(m.loColorMatrix)
Endfor
** Adjust these for preferred image quality vs. speed
*m.loGfxLeft.InterpolationMode = .Drawing2D.InterpolationMode.Default
*m.loGfxLeft.CompositingQuality = .Drawing2D.CompositingQuality.Default
*m.loGfxLeft.SmoothingMode = .Drawing2D.SmoothingMode.Default
** Use integers instead of floats for performance
m.loGfxLeft.UsePrecision = .F.
** Minor speed increase accessing this property once
m.lnHeightImage = m.loImageRight.Height
For m.lnCurrentStep = 1 To m.lnAlphaSteps
m.lnLeftStart = m.lnCurrentStep*m.lnWidthPart + m.lnWidthOpaque
** Draw partial right image to part
m.loGfxPart.DrawImage(m.loImageRight, ;
0,0,m.lnWidthPart,m.lnHeightImage, ;
m.lnLeftStart,0,m.lnWidthPart,m.lnHeightImage, ;
.GraphicsUnit.Pixel)
** Draw part to left image with Alpha blend
m.loGfxLeft.DrawImage(m.loBitmapPart, ;
m.lnLeftStart,0,m.lnWidthPart,m.lnHeightImage, ;
0,0,m.lnWidthPart,m.lnHeightImage, ;
.GraphicsUnit.Pixel, ;
laImageAttribs[m.lnCurrentStep])
Endfor
** Draw last opaque part of right image
m.loGfxLeft.DrawImage(m.loImageRight, ;
m.loImageRight.Width-m.lnWidthOpaque, 0, m.lnWidthOpaque, m.lnHeightImage, ;
m.loImageRight.Width-m.lnWidthOpaque, 0, m.lnWidthOpaque, m.lnHeightImage, ;
.GraphicsUnit.Pixel)
** Render to the screen
m.loGfxScreen = .Graphics.FromHWnd(_Screen.HWnd)
m.loGfxScreen.Clear(.Color.White)
m.loGfxScreen.DrawImage(m.loBitmapLeft,0,0,1024,768)
** Or you can save it to a file
**m.loBitmapLeft.Save("MyBlendedImage.png")
Endwith
Return
Endfunc
Thursday, October 02, 2008 3:43:52 PM (Eastern Daylight Time, UTC-04:00)
VFP Development | GDI Plus