This article demonstrates how to turn an image to a simple color picker.
Background
Actually, there is a lot of custom color pickers in the internet, in
MSDN, and also here at The Code Project. You will find a lot of similar
articles talking about custom color pickers but
I never saw an article discuss how to turn an image/bitmap to a color
picker, so I decided to give it a try, and here it is. I really hope it
will be helpful for fellow CodeProject members.
How to Get Color from a Bitmap
To get a pixel color from an image/bitmap, simply use the
Bitmap.GetPixel
method which is a part of the
Bitmap
class, and to do
that, you need to define an
Image
object, then pass the x and y coordinates of the pixel color to the
GetPixel
method, and you will get the color of the pixel.
The code looks something like:
' Create a Bitmap object
Dim bmp As New Bitmap("Grapes.jpg")
' Define the x-coordinate of the pixel to retrieve.
Dim x As Integer = 20
' Define the x-coordinate of the pixel to retrieve.
Dim y As Integer = 20
' Define the color and pass x, y coordinates to GetPixel Method
Dim pixelColor As Color = bmp.GetPixel(x, y)
Image Color Picker Control
The idea behind the image color picker is to pass a
byRef
point to the
MouseDown
and
MouseMove
events and get the mouse location, then pass the
same point to a private method to get the color at that point.
ImageColorPicker Files
- ImageColorPicker.vb: Extends the
Windows.Forms.Control
class.
Control Properties
Image
: used to set the user picked image/bitmap.
Public Property Image As Bitmap
Get
Return Me.originalBitmap
End Get
Set(ByVal value As Bitmap)
Me.originalBitmap = value
Me.DrawImage()
Me.Invalidate()
End Set
End Property
Color
: gets the color selected.
Public Property Color As Color
Get
Return Me.selectedColor
End Get
Set(ByVal value As Color)
Me.selectedColor = value
Me.PixelColorToPoint()
Me.DrawImage()
MyBase.Invalidate()
End Set
End Property
Control Events
ColorChanged
: occurs when the image pixel color changes, it also represents the control's DefaultEvent
.
'''
''' occurs when pixel color changed
'''
'''
Public Custom Event ColorChanged As EventHandler
AddHandler(ByVal value As EventHandler)
Me.Events.AddHandler("ColorChangedEvent", value)
End AddHandler
RemoveHandler(ByVal value As EventHandler)
Me.Events.RemoveHandler("ColorChangedEvent", value)
End RemoveHandler
RaiseEvent(ByVal sender As Object, ByVal e As System.EventArgs)
CType(Me.Events("ColorChangedEvent"), EventHandler).Invoke(sender, e)
End RaiseEvent
End Event
Control Methods
#Region " Methods"
Private Sub DrawImage()
If MyBase.Width > 0 AndAlso Me.originalBitmap IsNot Nothing Then
Me.pickerBitmap = New Bitmap(MyBase.ClientRectangle.Width - _
(Me.controlBorder * 2), MyBase.ClientRectangle.Height - _
(Me.controlBorder * 2))
Dim g As Graphics = Graphics.FromImage(Me.pickerBitmap)
Dim mode As SmoothingMode = g.SmoothingMode
Dim rect As New Rectangle(0, 0, Me.pickerBitmap.Width, _
Me.pickerBitmap.Height)
g.DrawImage(Me.originalBitmap, rect)
g.SmoothingMode = mode
g.Dispose()
End If
End Sub
'''
''' Get pixel color point
'''
''' pixel point
''' pixel color
''' width
''' height
'''
Private Sub PixelColorToPoint(ByRef pt As Point, ByVal pixelColor _
As Color, ByVal w As Integer, ByVal h As Integer)
pt.X = ((255 - pixelColor.GetBrightness()) * w) / 255
pt.Y = ((255 - pixelColor.GetSaturation()) * h) / 255
End Sub
Private Sub PixelColorToPoint()
PixelColorToPoint(New Point(Me.selectedPoint.X, Me.selectedPoint.Y), _
Me.selectedColor, MyBase.Width - (2 * Me.controlBorder), _
MyBase.Height - (Me.controlBorder))
End Sub
'''
''' check if pixel color point is within the boundary
''' of specified width and height and if not reset its value
'''
''' point
''' width
''' height
''' control border
'''
Private Sub CheckPixelColorPoint(ByRef pt As Point, ByVal w As _
Integer, ByVal h As Integer, ByVal border As Integer)
If (pt.X - border) < 0 Then
pt.X = border
End If
If pt.X > ((w - border) - 1) Then
pt.X = (w - border) - 1
End If
If (pt.Y - border) < 0 Then
pt.Y = border
End If
If pt.Y > ((h - border) - 1) Then
pt.Y = (h - border) - 1
End If
End Sub
'''
''' check if pixel color point is within the boundary
''' of the control width and height, if not reset its value
'''
'''
'''
Private Sub CheckPixelColorPoint(ByRef pt As Point)
Me.CheckPixelColorPoint(pt, MyBase.ClientRectangle.Width, _
MyBase.ClientRectangle.Height, controlBorder)
End Sub
'''
'''
'''
'''
'''
'''
Private Function HitTestPixelPoint(ByVal pt As Point) As Boolean
Me.CheckPixelColorPoint(pt)
If Me.originalBitmap IsNot Nothing Then
If (((pt.X - Me.controlBorder) >= 0) AndAlso _
((pt.X - Me.controlBorder) < Me.pickerBitmap.Width)) _
AndAlso (((pt.Y - Me.controlBorder) >= 0) _
AndAlso ((pt.Y - Me.controlBorder) < Me.pickerBitmap.Height)) Then
Dim pixelcolor As Color = _
Me.pickerBitmap.GetPixel((pt.X - Me.controlBorder), _
(pt.Y - Me.controlBorder))
If pixelcolor.A > 0 Then
Me.selectedColor = pixelcolor
Me.selectedPoint.X = pt.X - Me.controlBorder
Me.selectedPoint.Y = pt.Y - Me.controlBorder
Return True
End If
End If
End If
Return False
End Function
Protected Sub OnColorChanged(ByVal e As EventArgs)
Dim colorChangedHandler As EventHandler = _
CType(Me.Events("ColorChangedEvent"), EventHandler)
If (colorChangedHandler IsNot Nothing) Then
colorChangedHandler.Invoke(Me, e)
End If
End Sub
Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs)
MyBase.OnMouseDown(e)
If Me.HitTestPixelPoint(e.Location) Then
If Not Me.Focused Then
MyBase.Focus()
End If
MyBase.Invalidate()
Me.OnColorChanged(New EventArgs())
End If
End Sub
Protected Overrides Sub OnMouseMove(ByVal e As System.Windows.Forms.MouseEventArgs)
MyBase.OnMouseMove(e)
If (e.Button = Windows.Forms.MouseButtons.Left) _
AndAlso Me.HitTestPixelPoint(e.Location) Then
MyBase.Invalidate()
Me.OnColorChanged(New EventArgs())
End If
End Sub
Protected Overrides Sub OnEnter(ByVal e As System.EventArgs)
MyBase.OnEnter(e)
MyBase.Invalidate()
End Sub
Protected Overrides Sub OnLeave(ByVal e As System.EventArgs)
MyBase.OnLeave(e)
MyBase.Invalidate()
End Sub
Protected Overrides Sub OnSizeChanged(ByVal e As System.EventArgs)
Me.DrawImage()
MyBase.OnSizeChanged(e)
End Sub
Protected Overrides Sub OnResize(ByVal e As System.EventArgs)
Me.DrawImage()
MyBase.OnResize(e)
End Sub
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
Dim mode As SmoothingMode = e.Graphics.SmoothingMode
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias
If Me.pickerBitmap IsNot Nothing Then
Using lgb As New LinearGradientBrush(Me.ClientRectangle, _
Color.Black, Color.FromArgb(200, Color.Black), 90, True)
e.Graphics.FillRectangle(lgb, Me.ClientRectangle)
End Using
e.Graphics.DrawImage(Me.pickerBitmap, Me.controlBorder, Me.controlBorder)
End If
If Not Me.DesignMode Then
Dim r As New Rectangle((Me.controlBorder + Me.selectedPoint.X) - 5, _
(Me.controlBorder + Me.selectedPoint.Y) - 5, 10, 10)
Using sb As New SolidBrush(Me.selectedColor)
e.Graphics.FillRectangle(sb, r)
e.Graphics.DrawRectangle(Pens.White, r)
r.Inflate(1, 1)
e.Graphics.DrawRectangle(Pens.Black, r)
End Using
End If
End Sub
#End Region
Using the Control
Build the
ImageColorPicker
class, drag it to your form, then use it as follows:
Public Class Form1
Private selectedColor As Color
Private Sub ImagColorPicker1_ColorChanged(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles ImagColorPicker1.ColorChanged
selectedColor = Me.ImagColorPicker1.Color
Me.Invalidate()
End Sub
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
e.Graphics.FillRectangle(New SolidBrush(Me.selectedColor), _
New Rectangle(0, 0, 30, 30))
End Sub
End Class
Comments
Post a Comment