I was searching for this code today and thought I might share it. In my case, I have a clock on screen that I want to background color to blend in with the Background Image of a form. The ConvertTo24bpp sub wanted you to pass in an image, and I changed that to a bitmap.
The GetAverageColor1 function uses 24bppRgb to make the code faster (as I read). But eventually I want to turn it into a memory stream for better performance and I will probably reduce the size of the bitmap before passing it as well.
If you would like to see the whole post where I found the code, you can go here: https://social.msdn.microsoft.com/Fo...rum=vblanguage
I included how I call the code and it's in the BackgroundImageChanged Event of the Form. Not much to it, but I like the effect. Hope maybe someone enjoys using or seeing the code.
Code:
Private Sub ListviewForm_BackgroundImageChanged(sender As Object, e As EventArgs) Handles Me.BackgroundImageChanged
Dim NewBmp As Object = rk.GetValue("LastWallpaper")
Dim bmp As Bitmap = New Bitmap(CStr(NewBmp))
bmp = ConvertTo24bpp(bmp)
Dim clr As Color = GetAverageColor1(bmp)
LittleTime.BackColor = clr
rk.SetValue("ClockAutoBackground", True)
End Sub
Code:
Private Function GetAverageColor1(ByVal bm As Bitmap) As Color
If bm.PixelFormat <> PixelFormat.Format24bppRgb Then
MessageBox.Show("Image was not 24bppRgb")
Return Color.Black
End If
Dim bounds As New Rectangle(0, 0, bm.Width, bm.Height)
Dim bmd As BitmapData = bm.LockBits(bounds, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb)
' The stride is the width of 1 row of pixels in bytes. As 1 pixels requires 3 bytes of color
' information, you would think this would always be 3 * bm.Width - But it isn't. Each row of
' pixels is aligned so that it starts at a 4 byte boundary, this is done by padding rows with
' extra bytes if required. (might be 8 byte boundary on x64)
Dim stride As Integer = bmd.Stride
' An array to store the color information:
Dim pixels(bmd.Stride * bm.Height - 1) As Byte
' Copy it all out of the bitmap:
Marshal.Copy(bmd.Scan0, pixels, 0, pixels.Length)
bm.UnlockBits(bmd)
Dim totalR As UInteger
Dim totalG As UInteger
Dim totalB As UInteger
For y As Integer = 0 To bm.Height - 1
For x As Integer = 0 To bm.Width - 1
' Get the index of a pixel in the array.
' The index will be the number of bytes in all the rows above the pixel,
' which is (y * stride)
' plus the number of bytes in all the pixels to the left of it
' so add x*3:
Dim index As Integer = (y * stride) + (x * 3)
totalB += pixels(index)
totalG += pixels(index + 1)
totalR += pixels(index + 2)
Next
Next
' Average the components
Dim pixelCount As Integer = bm.Width * bm.Height
Dim averageR As Integer = CType(totalR \ pixelCount, Integer)
Dim averageG As Integer = CType(totalG \ pixelCount, Integer)
Dim averageB As Integer = CType(totalB \ pixelCount, Integer)
Return Color.FromArgb(averageR, averageG, averageB)
End Function
Code:
Public Shared Function ConvertTo24bpp(ByVal img As Bitmap) As Bitmap
Dim bmp As Bitmap = New Bitmap(img.Width, img.Height, PixelFormat.Format24bppRgb)
Using gr As Graphics = Graphics.FromImage(bmp)
gr.DrawImage(img, New Rectangle(0, 0, img.Width, img.Height))
End Using
Return bmp
End Function