65.9K
CodeProject is changing. Read more.
Home

How to get the dominant color in a bitmap

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.67/5 (2 votes)

Oct 13, 2011

CPOL
viewsIcon

20436

This tip shows how to pull the dominant color in a bitmap

Recently I was asked to make a control for a button similar to the Windows 7 taskbar buttons. I needed to pull the dominant color. To meet our needs, we had to do the following: > Skip any pixels which are black, white, or have an alpha of 0 > Weight the remaining pixels by their alpha. If there's alot of blue, but it's partly transparent, it should be weighted less then a red color which was fully opaque. > Round the RGB values to the nearest 10. So an RGB of 215,215,82 would count as 220,220,80. Visibly, there's not much difference, but it deals with instances where there's only a little bit of blue, and alot of red, but the red comes in many similar shades. Quickly, this is what I finally came up with. The RGBIndex processes the bitmap with the GetDominantColor function, and holds the color tallys in the Items collection. The indiviual RGBItems contain the RGB values and counts. There is some math that's done to handle the rounding to 10s which would not be necessary if you changed it to give each RGB it's own index.
Public Class RGBIndex

    Public Items As New Collection

    Public Sub AddItem(ByVal R As Integer, ByVal G As Integer, ByVal B As Integer, ByVal Count As Single)
        If (R = 0 And G = 0 And B = 0) Or (R >= 25 And G >= 25 And B >= 25) Then
            Exit Sub
        End If
        For Each i As RGBItem In Items
            If i.R = R And i.G = G And i.B = B Then
                i.Count += Count
                Exit Sub
            End If
        Next
        Dim i2 As New RGBItem(R, G, B, Count)
        Items.Add(i2)
    End Sub

    Public Function GetDominantColor(ByVal Image As Bitmap) As Color
        If Image Is Nothing Then
            Return Color.White
        End If
        For i As Integer = 0 To Image.Width - 1
            For j As Integer = 0 To Image.Height - 1
                Dim c As Color = Image.GetPixel(i, j)
                If c.A = 255 Then
                    AddItem(c.R / 10, c.G / 10, c.B / 10, c.A / 255)
                End If
            Next
        Next
        If Items.Count = 0 Then
            Return Color.White
        End If
        Dim Dominant As RGBItem = Items(1)
        For Each i As RGBItem In Items
            If i.Count > Dominant.Count Then
                Dominant = i
            End If
        Next
        Return Dominant.ReturnColor
    End Function
End Class


Public Class RGBItem
    Public R As Integer
    Public G As Integer
    Public B As Integer

    Public Count As Single = 0

    Public Sub New(ByVal R1 As Integer, ByVal G1 As Integer, ByVal B1 As Integer, ByVal Count1 As Single)
        R = R1
        G = G1
        B = B1
        Count = Count1
    End Sub

    Public Function ReturnColor() As Color
        Dim R1 As Integer = 10 * R
        Dim G1 As Integer = 10 * G
        Dim B1 As Integer = 10 * B
        If R1 > 255 Then
            R1 = 255
        End If
        If G1 > 255 Then
            G1 = 255
        End If
        If B1 > 255 Then
            B1 = 255
        End If
        Return Color.FromArgb(R1, G1, B1)
    End Function
End Class