2016-06-01

Bo Durban - Moxiedata Blog - Blending Two Images Using GDIPlusX

Original post by Bo Durban, replicated here because the original blog http://blog.moxiedata.com is not responding.
Copied from:
http://web.archive.org/web/20101017154139/http://blog.moxiedata.com/PermaLink,guid,7876146a-96e0-47dd-b442-271cad494a5d.aspx



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)
**********************************************************
* Author: Bo Durban *

   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


No comments:

Post a Comment