Thursday, 02 October 2008
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)





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)


   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.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)




** 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.



      For m.lnCurrentStep = 1 To m.lnAlphaSteps

         laImageAttribs[m.lnCurrentStep] = .Imaging.ImageAttributes.New()

         m.loColorMatrix.Matrix33 = m.lnCurrentStep/m.lnAlphaSteps




** 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, ;



** 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, ;





** 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, ;



** Render to the screen

      m.loGfxScreen = .Graphics.FromHWnd(_Screen.HWnd)




** Or you can save it to a file









Thursday, 02 October 2008 15:43:52 (Eastern Daylight Time, UTC-04:00)  #     Comments [12]   |