Blending (compositing with alpha) two images with GDI+

PictureBox1, PictureBox2, and PictureBox3 sit on a form. All are the same size. I want to blend the images in 1 and 2 together and put the blended image into PictureBox3, with PictureBox1 on top at an alpha level of my choosing. Thanks.
rdavis101Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Mike TomlinsonMiddle School Assistant TeacherCommented:
Public Class Form1
    Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

    Public Sub New()
        MyBase.New()

        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call

    End Sub

    'Form overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    Friend WithEvents PictureBox1 As System.Windows.Forms.PictureBox
    Friend WithEvents PictureBox2 As System.Windows.Forms.PictureBox
    Friend WithEvents PictureBox3 As System.Windows.Forms.PictureBox
    Friend WithEvents Button1 As System.Windows.Forms.Button
    Friend WithEvents Button2 As System.Windows.Forms.Button
    Friend WithEvents Button3 As System.Windows.Forms.Button
    Friend WithEvents NumericUpDown1 As System.Windows.Forms.NumericUpDown
    Friend WithEvents Label1 As System.Windows.Forms.Label
    Friend WithEvents OpenFileDialog1 As System.Windows.Forms.OpenFileDialog
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Me.PictureBox1 = New System.Windows.Forms.PictureBox
        Me.PictureBox2 = New System.Windows.Forms.PictureBox
        Me.PictureBox3 = New System.Windows.Forms.PictureBox
        Me.Button1 = New System.Windows.Forms.Button
        Me.Button2 = New System.Windows.Forms.Button
        Me.Button3 = New System.Windows.Forms.Button
        Me.NumericUpDown1 = New System.Windows.Forms.NumericUpDown
        Me.Label1 = New System.Windows.Forms.Label
        Me.OpenFileDialog1 = New System.Windows.Forms.OpenFileDialog
        CType(Me.NumericUpDown1, System.ComponentModel.ISupportInitialize).BeginInit()
        Me.SuspendLayout()
        '
        'PictureBox1
        '
        Me.PictureBox1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
        Me.PictureBox1.Location = New System.Drawing.Point(8, 8)
        Me.PictureBox1.Name = "PictureBox1"
        Me.PictureBox1.Size = New System.Drawing.Size(200, 200)
        Me.PictureBox1.TabIndex = 0
        Me.PictureBox1.TabStop = False
        '
        'PictureBox2
        '
        Me.PictureBox2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
        Me.PictureBox2.Location = New System.Drawing.Point(296, 8)
        Me.PictureBox2.Name = "PictureBox2"
        Me.PictureBox2.Size = New System.Drawing.Size(200, 200)
        Me.PictureBox2.TabIndex = 1
        Me.PictureBox2.TabStop = False
        '
        'PictureBox3
        '
        Me.PictureBox3.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
        Me.PictureBox3.Location = New System.Drawing.Point(168, 232)
        Me.PictureBox3.Name = "PictureBox3"
        Me.PictureBox3.Size = New System.Drawing.Size(200, 200)
        Me.PictureBox3.TabIndex = 2
        Me.PictureBox3.TabStop = False
        '
        'Button1
        '
        Me.Button1.Location = New System.Drawing.Point(216, 8)
        Me.Button1.Name = "Button1"
        Me.Button1.Size = New System.Drawing.Size(72, 32)
        Me.Button1.TabIndex = 3
        Me.Button1.Text = "Select Image"
        '
        'Button2
        '
        Me.Button2.Location = New System.Drawing.Point(504, 8)
        Me.Button2.Name = "Button2"
        Me.Button2.Size = New System.Drawing.Size(72, 32)
        Me.Button2.TabIndex = 4
        Me.Button2.Text = "Select Image"
        '
        'Button3
        '
        Me.Button3.Location = New System.Drawing.Point(392, 264)
        Me.Button3.Name = "Button3"
        Me.Button3.Size = New System.Drawing.Size(72, 32)
        Me.Button3.TabIndex = 5
        Me.Button3.Text = "Blend Images"
        '
        'NumericUpDown1
        '
        Me.NumericUpDown1.Location = New System.Drawing.Point(424, 232)
        Me.NumericUpDown1.Maximum = New Decimal(New Integer() {255, 0, 0, 0})
        Me.NumericUpDown1.Name = "NumericUpDown1"
        Me.NumericUpDown1.Size = New System.Drawing.Size(48, 20)
        Me.NumericUpDown1.TabIndex = 6
        Me.NumericUpDown1.Value = New Decimal(New Integer() {128, 0, 0, 0})
        '
        'Label1
        '
        Me.Label1.Location = New System.Drawing.Point(376, 232)
        Me.Label1.Name = "Label1"
        Me.Label1.Size = New System.Drawing.Size(40, 16)
        Me.Label1.TabIndex = 7
        Me.Label1.Text = "Alpha:"
        Me.Label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight
        '
        'Form1
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.ClientSize = New System.Drawing.Size(584, 446)
        Me.Controls.Add(Me.Label1)
        Me.Controls.Add(Me.NumericUpDown1)
        Me.Controls.Add(Me.Button3)
        Me.Controls.Add(Me.Button2)
        Me.Controls.Add(Me.Button1)
        Me.Controls.Add(Me.PictureBox3)
        Me.Controls.Add(Me.PictureBox2)
        Me.Controls.Add(Me.PictureBox1)
        Me.Name = "Form1"
        Me.Text = "AlphaBlend Two Images"
        CType(Me.NumericUpDown1, System.ComponentModel.ISupportInitialize).EndInit()
        Me.ResumeLayout(False)

    End Sub

#End Region

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        setImage(PictureBox1)
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        setImage(PictureBox2)
    End Sub

    Private Sub setImage(ByVal pb As PictureBox)
        OpenFileDialog1.Filter = "Image Files(*.BMP;*.JPG;*.GIF)|*.BMP;*.JPG;*.GIF|All files (*.*)|*.*"
        If OpenFileDialog1.ShowDialog = DialogResult.OK Then
            Try
                pb.Image = Image.FromFile(OpenFileDialog1.FileName)
            Catch ex As Exception
                MessageBox.Show(ex.Message, "Error Loading Image", MessageBoxButtons.OK, MessageBoxIcon.Error)
            End Try
        End If
    End Sub

    Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
        Button3.Enabled = False

        Dim tempBMP As Bitmap = New Bitmap(PictureBox1.Image)
        Dim clr As Color
        Dim x As Integer
        Dim y As Integer
        For y = 0 To tempBMP.Height - 1
            For x = 0 To tempBMP.Width - 1
                clr = tempBMP.GetPixel(x, y)
                tempBMP.SetPixel(x, y, _
                    Color.FromArgb(NumericUpDown1.Value, clr.R, clr.G, clr.B))
            Next x
        Next y

        Dim temp2BMP As Bitmap = New Bitmap(PictureBox2.Image)
        Dim gr As Graphics = Graphics.FromImage(temp2BMP)
        gr.DrawImage(tempBMP, 0, 0)
        PictureBox3.Image = temp2BMP
        PictureBox3.Refresh()
        tempBMP.Dispose()
        temp2BMP.Dispose()
        gr.Dispose()

        Button3.Enabled = True
    End Sub

End Class
0
rdavis101Author Commented:
Thanks...this is a great example project. I was wondering if there's a way of using compositing to set the alpha for the entire image, rather than by doing it by pixel, which could slow down on larger images?

Roger
0
Mike TomlinsonMiddle School Assistant TeacherCommented:
It is a pretty slow operation and I'm not sure if there is a way to do it without going pixel by pixel.  Unfortunately, I'm not a graphics wizard so that's the best solution I can  give you...  =\

It would probably run much faster using unmanaged C code with direct access to the API's but I can't help you there.

Hopefully some EE graphics gurus will pipe in and educate us both.  =)

~IM
0
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

rdavis101Author Commented:
Okay...had some time to check this out... Just add another button to the form you suggested. This blends images using the color matrix...change the .2 in the matrix below to be whatever you want...this value controls the alpha...seems to range from 0 to 1, but I'm not sure yet. Anyway, this approach does blend whole images at a time.

============

   Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
        PictureBox3.Image = New Bitmap(PictureBox3.Width, PictureBox3.Height)
        Dim G As Graphics = Graphics.FromImage(PictureBox3.Image)

        Dim cm As ColorMatrix = New ColorMatrix(New Single()() _
               {New Single() {1, 0, 0, 0, 0}, _
                New Single() {0, 1, 0, 0, 0}, _
                New Single() {0, 0, 1, 0, 0}, _
                New Single() {0, 0, 0, 0.2, 0}, _
                New Single() {0, 0, 0, 0, 1}})

        Dim IA As New ImageAttributes

        IA.SetColorMatrix(CM, ColorMatrixFlag.Default, ColorAdjustType.Bitmap)
        G.DrawImage(PictureBox1.Image, 0, 0)
        G.DrawImage(PictureBox2.Image, PictureBox3.ClientRectangle, 0, 0, PictureBox3.Width, PictureBox3.Height, GraphicsUnit.Pixel, IA)

================
    End Sub
0
Mike TomlinsonMiddle School Assistant TeacherCommented:
Well that certainly is alot faster than going pixel by pixel.  =)

Thanx for posting it.  I'm still trying to figure out how it works.  Darned documentation...

You can post a request in the Support TA to PAQ the question and refund your points since you answered your own question.

~IM
0
CetusMODCommented:
Question PAQ'd
125 points refunded.

CetusMOD
Community Support Moderator
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic.NET

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.