Created
February 6, 2016 20:50
-
-
Save KareemMAX/736f139dee812b556b17 to your computer and use it in GitHub Desktop.
HSB color picker with OpenTK and VB.net
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _ | |
Partial Class ColorPicker | |
Inherits System.Windows.Forms.UserControl | |
'UserControl overrides dispose to clean up the component list. | |
<System.Diagnostics.DebuggerNonUserCode()> _ | |
Protected Overrides Sub Dispose(ByVal disposing As Boolean) | |
Try | |
If disposing AndAlso components IsNot Nothing Then | |
components.Dispose() | |
End If | |
Finally | |
MyBase.Dispose(disposing) | |
End Try | |
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. | |
<System.Diagnostics.DebuggerStepThrough()> _ | |
Private Sub InitializeComponent() | |
Me.components = New System.ComponentModel.Container() | |
Me.HSV = New OpenTK.GLControl() | |
Me.Hue = New OpenTK.GLControl() | |
Me.Saturation = New OpenTK.GLControl() | |
Me.Value = New OpenTK.GLControl() | |
Me.CurrentColor = New OpenTK.GLControl() | |
Me.MouseDown = New System.Windows.Forms.Timer(Me.components) | |
Me.SuspendLayout() | |
' | |
'HSV | |
' | |
Me.HSV.Anchor = CType(((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Left) _ | |
Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) | |
Me.HSV.BackColor = System.Drawing.Color.Black | |
Me.HSV.Location = New System.Drawing.Point(3, 3) | |
Me.HSV.Name = "HSV" | |
Me.HSV.Size = New System.Drawing.Size(250, 250) | |
Me.HSV.TabIndex = 0 | |
Me.HSV.VSync = False | |
' | |
'Hue | |
' | |
Me.Hue.Anchor = CType(((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left) _ | |
Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) | |
Me.Hue.BackColor = System.Drawing.Color.Black | |
Me.Hue.Location = New System.Drawing.Point(31, 263) | |
Me.Hue.Name = "Hue" | |
Me.Hue.Size = New System.Drawing.Size(28, 217) | |
Me.Hue.TabIndex = 1 | |
Me.Hue.VSync = False | |
' | |
'Saturation | |
' | |
Me.Saturation.Anchor = CType(((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left) _ | |
Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) | |
Me.Saturation.BackColor = System.Drawing.Color.Black | |
Me.Saturation.Location = New System.Drawing.Point(82, 263) | |
Me.Saturation.Name = "Saturation" | |
Me.Saturation.Size = New System.Drawing.Size(28, 217) | |
Me.Saturation.TabIndex = 2 | |
Me.Saturation.VSync = False | |
' | |
'Value | |
' | |
Me.Value.Anchor = CType(((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left) _ | |
Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) | |
Me.Value.BackColor = System.Drawing.Color.Black | |
Me.Value.Location = New System.Drawing.Point(145, 263) | |
Me.Value.Name = "Value" | |
Me.Value.Size = New System.Drawing.Size(28, 217) | |
Me.Value.TabIndex = 3 | |
Me.Value.VSync = False | |
' | |
'CurrentColor | |
' | |
Me.CurrentColor.Anchor = CType(((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left) _ | |
Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) | |
Me.CurrentColor.BackColor = System.Drawing.Color.Black | |
Me.CurrentColor.Location = New System.Drawing.Point(201, 263) | |
Me.CurrentColor.Name = "CurrentColor" | |
Me.CurrentColor.Size = New System.Drawing.Size(28, 217) | |
Me.CurrentColor.TabIndex = 4 | |
Me.CurrentColor.VSync = False | |
' | |
'MouseDown | |
' | |
Me.MouseDown.Enabled = True | |
Me.MouseDown.Interval = 1 | |
' | |
'ColorPicker | |
' | |
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) | |
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font | |
Me.Controls.Add(Me.CurrentColor) | |
Me.Controls.Add(Me.Value) | |
Me.Controls.Add(Me.Saturation) | |
Me.Controls.Add(Me.Hue) | |
Me.Controls.Add(Me.HSV) | |
Me.Name = "ColorPicker" | |
Me.Size = New System.Drawing.Size(257, 494) | |
Me.ResumeLayout(False) | |
End Sub | |
Friend WithEvents HSV As OpenTK.GLControl | |
Friend WithEvents Hue As OpenTK.GLControl | |
Friend WithEvents Saturation As OpenTK.GLControl | |
Friend WithEvents Value As OpenTK.GLControl | |
Friend WithEvents CurrentColor As OpenTK.GLControl | |
Friend WithEvents MouseDown As Timer | |
End Class |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Imports System.ComponentModel | |
Imports OpenTK.Graphics.OpenGL | |
Public Class ColorPicker | |
<Description("Render it or not (only used when design because when it became false in design mode it crashs VS and can be removed in the release)"), Category("Behavior")> | |
Property InDesignMode As Boolean = True | |
Dim TheColor As Color = Color.Red | |
<Description("The current color"), Category("Appearance")> | |
Property Color As Color | |
Set(value As Color) | |
If value.A <> 0 AndAlso value.A <> 255 Then | |
value = Color.FromArgb(255, value.R, value.G, value.B) | |
End If | |
TheColor = value | |
End Set | |
Get | |
Return TheColor | |
End Get | |
End Property | |
Private Sub HSV_Paint(sender As Object, e As PaintEventArgs) Handles HSV.Paint | |
If InDesignMode Then Exit Sub | |
HSV.MakeCurrent() | |
GL.ClearColor(BackColor) | |
'First Clear Buffers | |
GL.Clear(ClearBufferMask.ColorBufferBit) | |
GL.Begin(BeginMode.Polygon) | |
GL.Color3(HSVtoRGB(0, 0, RGBtoHSV(Color).Value)) | |
GL.Vertex2(0, 0) | |
For I As Double = 0 To 2 * Math.PI Step Math.PI / 24 | |
GL.Color3(HSVtoRGB((I * 360) / (2 * Math.PI), 100, RGBtoHSV(Color).Value)) | |
GL.Vertex2(Math.Cos(I), Math.Sin(I)) | |
Next | |
GL.End() | |
GL.LineWidth(1.5) | |
GL.Begin(BeginMode.LineStrip) | |
GL.Color3(Color.White) | |
For I As Double = 0 To 2 * Math.PI Step Math.PI / 24 | |
GL.Vertex2(Math.Cos(I) * 0.05 + (Math.Cos((Color.GetHue * (2 * Math.PI)) / 360) * (RGBtoHSV(Color).Saturation / 100)), Math.Sin(I) * 0.05 + (Math.Sin((Color.GetHue * (2 * Math.PI)) / 360) * (RGBtoHSV(Color).Saturation / 100))) | |
Next | |
GL.End() | |
HSV.SwapBuffers() | |
HSV.Context.MakeCurrent(Nothing) | |
End Sub | |
Function HSVtoRGB(ByVal H As Integer, ByVal S As Integer, ByVal V As Integer) As Color | |
''# Scale the Saturation and Value components to be between 0 and 1 | |
Dim hue As Decimal = H | |
Dim sat As Decimal = S / 100D | |
Dim val As Decimal = V / 100D | |
Dim r As Decimal | |
Dim g As Decimal | |
Dim b As Decimal | |
If sat = 0 Then | |
''# If the saturation is 0, then all colors are the same. | |
''# (This is some flavor of gray.) | |
r = val | |
g = val | |
b = val | |
Else | |
''# Calculate the appropriate sector of a 6-part color wheel | |
Dim sectorPos As Decimal = hue / 60D | |
Dim sectorNumber As Integer = CInt(Math.Floor(sectorPos)) | |
''# Get the fractional part of the sector | |
''# (that is, how many degrees into the sector you are) | |
Dim fractionalSector As Decimal = sectorPos - sectorNumber | |
''# Calculate values for the three axes of the color | |
Dim p As Decimal = val * (1 - sat) | |
Dim q As Decimal = val * (1 - (sat * fractionalSector)) | |
Dim t As Decimal = val * (1 - (sat * (1 - fractionalSector))) | |
''# Assign the fractional colors to red, green, and blue | |
''# components based on the sector the angle is in | |
Select Case sectorNumber | |
Case 0, 6 | |
r = val | |
g = t | |
b = p | |
Case 1 | |
r = q | |
g = val | |
b = p | |
Case 2 | |
r = p | |
g = val | |
b = t | |
Case 3 | |
r = p | |
g = q | |
b = val | |
Case 4 | |
r = t | |
g = p | |
b = val | |
Case 5 | |
r = val | |
g = p | |
b = q | |
End Select | |
End If | |
''# Scale the red, green, and blue values to be between 0 and 255 | |
r *= 255 | |
g *= 255 | |
b *= 255 | |
''# Return a color in the new color space | |
Return Color.FromArgb(CInt(Math.Round(r, MidpointRounding.AwayFromZero)), | |
CInt(Math.Round(g, MidpointRounding.AwayFromZero)), | |
CInt(Math.Round(b, MidpointRounding.AwayFromZero))) | |
End Function | |
Function RGBtoHSV(ByVal Color As Color) As HSV | |
''# Normalize the RGB values by scaling them to be between 0 and 1 | |
Dim red As Decimal = Color.R / 255D | |
Dim green As Decimal = Color.G / 255D | |
Dim blue As Decimal = Color.B / 255D | |
Dim minValue As Decimal = Math.Min(red, Math.Min(green, blue)) | |
Dim maxValue As Decimal = Math.Max(red, Math.Max(green, blue)) | |
Dim delta As Decimal = maxValue - minValue | |
Dim h As Decimal | |
Dim s As Decimal | |
Dim v As Decimal = maxValue | |
''# Calculate the hue (in degrees of a circle, between 0 and 360) | |
Select Case maxValue | |
Case red | |
If green >= blue Then | |
If delta = 0 Then | |
h = 0 | |
Else | |
h = 60 * (green - blue) / delta | |
End If | |
ElseIf green < blue Then | |
h = 60 * (green - blue) / delta + 360 | |
End If | |
Case green | |
h = 60 * (blue - red) / delta + 120 | |
Case blue | |
h = 60 * (red - green) / delta + 240 | |
End Select | |
''# Calculate the saturation (between 0 and 1) | |
If maxValue = 0 Then | |
s = 0 | |
Else | |
s = 1D - (minValue / maxValue) | |
End If | |
''# Scale the saturation and value to a percentage between 0 and 100 | |
s *= 100 | |
v *= 100 | |
''# Return a color in the new color space | |
Return New HSV(CInt(Math.Round(h, MidpointRounding.AwayFromZero)), | |
CInt(Math.Round(s, MidpointRounding.AwayFromZero)), | |
CInt(Math.Round(v, MidpointRounding.AwayFromZero))) | |
End Function | |
Private Sub CurrentColor_Paint(sender As Object, e As PaintEventArgs) Handles CurrentColor.Paint | |
If InDesignMode Then Exit Sub | |
CurrentColor.MakeCurrent() | |
GL.ClearColor(Color) | |
GL.Clear(ClearBufferMask.ColorBufferBit) | |
CurrentColor.SwapBuffers() | |
CurrentColor.Context.MakeCurrent(Nothing) | |
End Sub | |
Private Sub Hue_Paint(sender As Object, e As PaintEventArgs) Handles Hue.Paint | |
If InDesignMode Then Exit Sub | |
Hue.MakeCurrent() | |
GL.Clear(ClearBufferMask.ColorBufferBit) | |
GL.Begin(BeginMode.QuadStrip) | |
For I As Single = -1 To 1 Step 0.01 | |
GL.Color3(HSVtoRGB(((I + 1) * 360) / 2, 100, 100)) | |
GL.Vertex2(-1, -I) | |
GL.Vertex2(1, -I) | |
Next | |
GL.End() | |
GL.LineWidth(3) | |
GL.Begin(BeginMode.Lines) | |
GL.Color3(Color.White) | |
GL.Vertex2(-1, -((2.0F * (Hue.Height / 360) * Color.GetHue) / Hue.Height - 1.0F)) | |
GL.Vertex2(1, -((2.0F * (Hue.Height / 360) * Color.GetHue) / Hue.Height - 1.0F)) | |
GL.End() | |
Hue.SwapBuffers() | |
Hue.Context.MakeCurrent(Nothing) | |
End Sub | |
Private Sub Saturation_Paint(sender As Object, e As PaintEventArgs) Handles Saturation.Paint | |
If InDesignMode Then Exit Sub | |
Saturation.MakeCurrent() | |
GL.Clear(ClearBufferMask.ColorBufferBit) | |
GL.Begin(BeginMode.Quads) | |
GL.Color3(HSVtoRGB(Color.GetHue, 100, RGBtoHSV(Color).Value)) | |
GL.Vertex2(-1, 1) | |
GL.Vertex2(1, 1) | |
GL.Color3(HSVtoRGB(Color.GetHue, 0, RGBtoHSV(Color).Value)) | |
GL.Vertex2(1, -1) | |
GL.Vertex2(-1, -1) | |
GL.End() | |
GL.LineWidth(3) | |
GL.Begin(BeginMode.Lines) | |
GL.Color3(Color.White) | |
GL.Vertex2(-1, ((2.0F * (Saturation.Height / 100) * RGBtoHSV(Color).Saturation) / Saturation.Height - 1.0F)) | |
GL.Vertex2(1, ((2.0F * (Saturation.Height / 100) * RGBtoHSV(Color).Saturation) / Saturation.Height - 1.0F)) | |
GL.End() | |
Saturation.SwapBuffers() | |
Saturation.Context.MakeCurrent(Nothing) | |
End Sub | |
Private Sub Value_Paint(sender As Object, e As PaintEventArgs) Handles Value.Paint | |
If InDesignMode Then Exit Sub | |
Value.MakeCurrent() | |
GL.Clear(ClearBufferMask.ColorBufferBit) | |
GL.Begin(BeginMode.Quads) | |
GL.Color3(HSVtoRGB(Color.GetHue, Color.GetSaturation * 100, 100)) | |
GL.Vertex2(-1, 1) | |
GL.Vertex2(1, 1) | |
GL.Color3(HSVtoRGB(Color.GetHue, Color.GetSaturation * 100, 0)) | |
GL.Vertex2(1, -1) | |
GL.Vertex2(-1, -1) | |
GL.End() | |
GL.LineWidth(3) | |
GL.Begin(BeginMode.Lines) | |
GL.Color3(Color.White) | |
GL.Vertex2(-1, ((2.0F * ((Value.Height / 100) * RGBtoHSV(Color).Value)) / Value.Height - 1.0F)) | |
GL.Vertex2(1, ((2.0F * ((Value.Height / 100) * RGBtoHSV(Color).Value)) / Value.Height - 1.0F)) | |
GL.End() | |
Value.SwapBuffers() | |
Value.Context.MakeCurrent(Nothing) | |
End Sub | |
Dim ValueDown As Boolean | |
Dim SaturationDown As Boolean | |
Dim HueDown As Boolean | |
Dim HSVDown As Boolean | |
Private Sub Value_MouseDown(sender As Object, e As MouseEventArgs) Handles Value.MouseDown | |
If e.Button = MouseButtons.Left Then | |
ValueDown = True | |
End If | |
End Sub | |
Private Sub Value_MouseUp(sender As Object, e As MouseEventArgs) Handles Value.MouseUp | |
ValueDown = False | |
End Sub | |
Private Sub Saturation_MouseDown(sender As Object, e As MouseEventArgs) Handles Saturation.MouseDown | |
If e.Button = MouseButtons.Left Then | |
SaturationDown = True | |
End If | |
End Sub | |
Private Sub Saturation_MouseUp(sender As Object, e As MouseEventArgs) Handles Saturation.MouseUp | |
SaturationDown = False | |
End Sub | |
Private Sub Hue_MouseDown(sender As Object, e As MouseEventArgs) Handles Hue.MouseDown | |
If e.Button = MouseButtons.Left Then | |
HueDown = True | |
End If | |
End Sub | |
Private Sub Hue_MouseUp(sender As Object, e As MouseEventArgs) Handles Hue.MouseUp | |
HueDown = False | |
End Sub | |
Private Sub MouseDown_Tick(sender As Object, e As EventArgs) Handles MouseDown.Tick | |
If ValueDown Then | |
Dim Point As Point = Value.PointToClient(New Point(Cursor.Position)) | |
If Point.X < 0 OrElse Point.X > Value.Width OrElse Point.Y < 0 OrElse Point.Y > Value.Height Then | |
Exit Sub | |
End If | |
Color = HSVtoRGB(Color.GetHue, Color.GetSaturation * 100, (100 / Value.Height) * Math.Abs(Point.Y - Value.Height)) | |
Refresh() | |
ElseIf SaturationDown Then | |
Dim Point As Point = Saturation.PointToClient(New Point(Cursor.Position)) | |
If Point.X < 0 OrElse Point.X > Saturation.Width OrElse Point.Y < 0 OrElse Point.Y > Saturation.Height Then | |
Exit Sub | |
End If | |
Color = HSVtoRGB(Color.GetHue, (100 / Saturation.Height) * Math.Abs(Point.Y - Saturation.Height), RGBtoHSV(Color).Value) | |
Refresh() | |
ElseIf HueDown Then | |
Dim Point As Point = Hue.PointToClient(New Point(Cursor.Position)) | |
If Point.X < 0 OrElse Point.X > Hue.Width OrElse Point.Y < 0 OrElse Point.Y > Hue.Height Then | |
Exit Sub | |
End If | |
Color = HSVtoRGB((360 / Hue.Height) * Point.Y, RGBtoHSV(Color).Saturation, RGBtoHSV(Color).Value) | |
Refresh() | |
ElseIf HSVDown Then | |
Dim Point As Point = HSV.PointToClient(New Point(Cursor.Position)) | |
If Point.X < 0 OrElse Point.X > HSV.Width OrElse Point.Y < 0 OrElse Point.Y > HSV.Height Then | |
Exit Sub | |
End If | |
Dim HSVColor As New HSV(-Math.Atan2((Point.Y - HSV.Height / 2), (Point.X - HSV.Width / 2)) * 180 / Math.PI, ((((Point.X - HSV.Width / 2) ^ 2) + ((Point.Y - HSV.Height / 2) ^ 2)) ^ (1 / 2)) * 100 / (0.5 * HSV.Width), RGBtoHSV(Color).Value) | |
If HSVColor.Saturation > 100 Then HSVColor.Saturation = 100 | |
If HSVColor.Hue > 360 Then | |
HSVColor.Hue -= 360 | |
ElseIf HSVColor.Hue < 0 Then | |
HSVColor.Hue += 360 | |
End If | |
Color = HSVtoRGB(HSVColor.Hue, HSVColor.Saturation, HSVColor.Value) | |
Refresh() | |
End If | |
End Sub | |
Private Sub HSV_MouseDown(sender As Object, e As MouseEventArgs) Handles HSV.MouseDown | |
If e.Button = MouseButtons.Left Then | |
HSVDown = True | |
End If | |
End Sub | |
Private Sub HSV_MouseUp(sender As Object, e As MouseEventArgs) Handles HSV.MouseUp | |
HSVDown = False | |
End Sub | |
End Class | |
Public Class HSV | |
Property Hue As Integer | |
Property Saturation As Integer | |
Property Value As Integer | |
Sub New(H As Integer, S As Integer, V As Integer) | |
Hue = H | |
Saturation = S | |
Value = V | |
End Sub | |
End Class |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment