StealthRT StealthRT - 6 months ago 25
Vb.net Question

Merge an image, a background and Text into a single image

I found this code here:

Private _BackgroundColours As New List(Of String)() From { _
"339966", _
"3366CC", _
"CC33FF", _
"FF5050" _
}

Public Function GenerateRactangle(firstName As String, lastName As String) As MemoryStream
Dim imgSize() As Integer = {800, 800}
Dim avatarString As String = String.Format("{0}{1}", firstName(0), lastName(0)).ToUpper()
Dim bgColour = _BackgroundColours(New Random().[Next](0, _BackgroundColours.Count - 1))
Dim bmp As Bitmap = New Bitmap(imgSize(0), imgSize(1))
Dim sf As StringFormat = New StringFormat()
Dim ms As MemoryStream = New MemoryStream()
Dim font As Font = New Font("Arial", 172, FontStyle.Bold, GraphicsUnit.Pixel)
Dim graphics__1 As Graphics = Nothing

sf.Alignment = StringAlignment.Center
sf.LineAlignment = StringAlignment.Center

graphics__1 = Graphics.FromImage(bmp)
graphics__1.Clear(DirectCast(New ColorConverter().ConvertFromString("#" + bgColour), Color))
graphics__1.SmoothingMode = SmoothingMode.AntiAlias
graphics__1.TextRenderingHint = TextRenderingHint.AntiAliasGridFit
graphics__1.DrawString(avatarString, font, New SolidBrush(Color.WhiteSmoke), New RectangleF(0, 0, imgSize(0), imgSize(1)), sf)
graphics__1.Flush()
bmp.Save(ms, ImageFormat.Png)

Return ms
End Function


On stackoverflow and it works great. However, I am in need of using a transparent PNG image in the background with the color changing background color.

What it currently looks like:

enter image description here

What I am looking for it to look like:

enter image description here

With the PNG image being this that was added:

enter image description here

I am hoping someone with more knowledge about the graphics calls can let me know how to go about doing this.

Answer

The method you found leaves at least the Font and Grahics objects undisposed, so if that is used as a factory to process numerous images, it will leak. Things like picking a random back color might be better left to the calling code, and a memstream seems an odd return type choice.

A general method to create a background, overlay a PNG and apply the text to it:

Private Function CreateLabeledAvatar(av As Image, bg As Color, text As String) As Image

    ' fixed size?
    Dim bmp As New Bitmap(250, 250)
    Using g As Graphics = Graphics.FromImage(bmp)
        Using br As New SolidBrush(bg)
            g.FillRectangle(br, 0, 0, bmp.Width, bmp.Height)
        End Using
        g.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic
        g.CompositingQuality = CompositingQuality.HighQuality
        g.TextRenderingHint = TextRenderingHint.AntiAlias
        g.SmoothingMode = SmoothingMode.HighQuality
        g.DrawImage(av, 0, 0, bmp.Width, bmp.Height)

        ' lastly the text, centred on the new image
        ' could also draw to the AV passed to center on IT
        Using fnt As New Font("Arial", 32, FontStyle.Bold, GraphicsUnit.Pixel)
            TextRenderer.DrawText(g, text, fnt, New Rectangle(0, 0, 250, 250), 
                  Color.WhiteSmoke,
                  TextFormatFlags.HorizontalCenter Or TextFormatFlags.VerticalCenter)
        End Using

    End Using

    Return bmp
End Function

Sample usage:

Dim av = Image.FromFile("C:\temp\maleAV.png")
Dim bg = Color.FromArgb(62, 103, 207)

Dim newImg = CreateLabeledAvatar(av, bg, "BB")
pb1.Image = newImg

av.Dispose()

When your code is done with it, newImg should also be disposed.

There are other params you might want to be passed or set such as the desired size, font size and maybe even the text color. Passing any more, though and I would make it a class, so if it is used to processed a lot of them, many params could be set once.

Result:

enter image description here

The image created was 250,250, it is displayed in a 150x150 PBox

Comments