Microsoft Small Basic

Program Listing: MXV150-0
' Colors v0.2 - (C) 2011 Nonki Takahashi
' shows 140 named colors, RGB and HSL
'
' History
' 2011/04/04 Created (280 lines MXV150)
' 2011/04/05 Added RGB to HSL conversion (433 lines MXV150-0)
'
' Reference
' [1] "Microsoft Small Basic - An Introduction to Programming"
' [2] James D. Foley, Andries Van Dam "Fundamentals of Interactive Computer Graphics" 1982
'
' Constant
VERSION = "v0.2"
UNDEFINED = "N/A"
CRLF = Text.GetCharacter(13) + Text.GetCharacter(10)

' Main
GraphicsWindow.Height = 600
GraphicsWindow.Width = 360
GraphicsWindow.Show()
GraphicsWindow.Title = "Colors " + VERSION
ColorName_Init()
For iFamily = 1 To 10
GraphicsWindow.Clear()
Console_Init()
ColorPick_Init()
GraphicsWindow.BrushColor = "#4F81BD"
GraphicsWindow.DrawText(10, 10, sColorFamily[iFamily])
iLine = 1
For iColor = iColorFast[iFamily] To iColorLast[iFamily]
GraphicsWindow.BrushColor = sColorName[iColor]
GraphicsWindow.FillRectangle(10, 20 * iLine + 10, 250, 20)
sColor = GraphicsWindow.BrushColor
Color_RGBtoHSL()
Color_GrayFromLightness()
GraphicsWindow.BrushColor = sGray
GraphicsWindow.FillRectangle(260, 20 * iLine + 10, 40, 20)
If rLightness > 0.45 Then
GraphicsWindow.BrushColor = "Black"
Else
GraphicsWindow.BrushColor = "White"
EndIf
GraphicsWindow.DrawText(20, 20 * iLine + 10, sColorName[iColor])
GraphicsWindow.DrawText(180, 20 * iLine + 10, sColor)
GraphicsWindow.DrawText(268, 20 * iLine + 10, Math.Round(rLightness * 255))
iLine = iLine + 1
EndFor
bButtonNotClicked = "True"
Controls.ButtonClicked = Console_OnButtonClicked
ColorPick_Show()
bMouseMoved = "False"
While bButtonNotClicked
If bMouseMoved Then
Shapes.Move(oRect, iMX + 10, iMY + 10)
Shapes.Move(oText, iMX + 14, iMY + 14)
sColor = GraphicsWindow.GetPixel(iMX, iMY)
Color_RGBtoHSL()
Color_HSLtoRGB()
If rHue = UNDEFINED Then
iHue = rHue
Else
iHue = Math.Round(rHue * 256 / 360)
EndIf
sText = sColor + CRLF + "H=" + iHue + CRLF + "S=" + Math.Round(rSaturation * 255) + CRLF + "L=" + Math.Round(rLightness * 255)
Shapes.SetText(oText, sText)
bMouseMoved = "False"
Else
Program.Delay(200)
EndIf
EndWhile
If iFamily = 10 Then
iFamily = 0
EndIf
EndFor

' Console | Initialization
Sub Console_Init
GraphicsWindow.BrushColor = "White"
GraphicsWindow.FillRectangle(0, 0, 600, 360)
GraphicsWindow.BrushColor = "Black"
oNextButton = Controls.AddButton("Next", 310, 20)
EndSub

' Console | On button clicked
Sub Console_OnButtonClicked
bButtonNotClicked = "False"
EndSub

' Color | Convert HSL to RGB
' in: rHue - [0, 360) or UNDEFINED
' in: rLightness - [0, 1]
' in: rSaturation - [0, 1]
' out: sColor - "#rrggbb"
Sub Color_HSLtoRGB
If rLightness <= 0.5 Then
rN2 = rLightness * (1 + rSaturation)
Else
rN2 = rLightness + rSaturation - rLightness * rSaturation
EndIf
rN1 = 2 * rLightness - rN2
If rSaturation = 0 Then
iR = Math.Round(rLightness * 255)
iG = Math.Round(rLightness * 255)
iB = Math.Round(rLightness * 255)
Else
rH = rHue + 120
Color_Value()
iR = iValue
rH = rHue
Color_Value()
iG = iValue
rH = rHue - 120
Color_Value()
iB = iValue
EndIf
sColor = GraphicsWindow.GetColorFromRGB(iR, iG, iB)
EndSub

' Color | Function value
' in: rN1, rN2
' in: rH - [-120, 480)
' out: iValue - 0..255
Sub Color_Value
If rH >= 360 Then
rH = rH - 360
EndIF
If rH < 0 Then
rH = rH + 360
EndIF
If rH < 60 Then
rV = rN1 + (rN2 - rN1) * rH / 60
ElseIf rH < 180 Then
rV = rN2
ElseIf rH < 240 Then
rV = rN1 + (rN2 - rN1) * (240 - rH) / 60
Else
rV = rN1
EndIf
iValue = Math.Round(rV * 255)
EndSub

' Color | Convert RGB to HSL
' in: sColor - "#rrggbb"
' out: rHue - [0, 360) or UNDEFINED
' out: rLightness - (0, 1)
' out: rSaturation - (0, 1)
Sub Color_RGBtoHSL
sR = Text.GetSubText(sColor, 2, 2)
sG = Text.GetSubText(sColor, 4, 2)
sB = Text.GetSubText(sColor, 6, 2)
sHex = sR
Math_Hex2Dec()
' rR = iDec / 255 ' occurs Math.Max() bug
rR = Math.Round(iDec / 255 * 10000) / 10000
sHex = sG
Math_Hex2Dec()
' rG = iDec / 255 ' occurs Math.Max() bug
rG = Math.Round(iDec / 255 * 10000) / 10000
sHex = sB
Math_Hex2Dec()
' rB = iDec / 255 ' occurs Math.Max() bug
rB = Math.Round(iDec / 255 * 10000) / 10000
rMax = Math.Max(rR, rG)
rMax = Math.Max(rMax, rB)
rMin = Math.Min(rR, rG)
rMin = Math.Min(rMin, rB)
rLightness = (rMax + rMin) / 2
If rMax = rMin Then ' rR = rG = rB
rSaturation = 0
rHue = UNDEFINED
Else
If rLightness <= 0.5 Then
rSaturation = (rMax - rMin) / (rMax + rMin)
Else
rSaturation = (rMax - rMin) / (2 - rMax - rMin)
EndIf
rRC = (rMax - rR) / (rMax - rMin)
rGC = (rMax - rG) / (rMax - rMin)
rBC = (rMax - rB) / (rMax - rMin)
If rR = rMax Then ' between Yellow and Magenta
rHue = rBC - rGC
ElseIf rG = rMax Then ' between Cyan and Yellow
rHue = 2 + rRC - rBC
ElseIf rB = rMax Then ' between Magenta and Cyan
rHue = 4 + rGC - rRC
Else
TextWindow.WriteLine("Error:")
TextWindow.WriteLine("rMax=" + rMax)
TextWindow.WriteLine("rR=" + rR + ",sR=" + sR)
TextWindow.WriteLine("rG=" + rG + ",sG=" + sG)
TextWindow.WriteLine("rB=" + rB + ",sB=" + sB)
EndIf
rHue = rHue * 60
If rHue < 0 Then
rHue = rHue + 360
EndIf
EndIf
EndSub

' Color | Gray from lightness
' in: rLightness - 0..255
' out: sGray - "#rrggbb"
Sub Color_GrayFromLightness
iGray = Math.Round(rLightness * 255)
sGray = GraphicsWindow.GetColorFromRGB(iGray, iGray, iGray)
EndSub

' Color name | Initialization
Sub ColorName_Init
sColorFamily[1] = "Red Colors"
iColorFast[1] = 1
iColorLast[1] = 9
sColorName[1] = "IndianRed"
sColorName[2] = "LightCoral"
sColorName[3] = "Salmon"
sColorName[4] = "DarkSalmon"
sColorName[5] = "LightSalmon"
sColorName[6] = "Crimson"
sColorName[7] = "Red"
sColorName[8] = "FireBrick"
sColorName[9] = "DarkRed"

sColorFamily[2] = "Pink Colors"
iColorFast[2] = 10
iColorLast[2] = 15
sColorName[10] = "Pink"
sColorName[11] = "LightPink"
sColorName[12] = "HotPink"
sColorName[13] = "DeepPink"
sColorName[14] = "MediumVioletRed"
sColorName[15] = "PaleVioletRed"

sColorFamily[3] = "Orange Colors"
iColorFast[3] = 16
iColorLast[3] = 21
sColorName[16] = "LightSalmon"
sColorName[17] = "Coral"
sColorName[18] = "Tomato"
sColorName[19] = "OrangeRed"
sColorName[20] = "DarkOrange"
sColorName[21] = "Orange"

sColorFamily[4] = "Yellow Colors"
iColorFast[4] = 22
iColorLast[4] = 32
sColorName[22] = "Gold"
sColorName[23] = "Yellow"
sColorName[24] = "LightYellow"
sColorName[25] = "LemonChiffon"
sColorName[26] = "LightGoldenrodYellow"
sColorName[27] = "PapayaWhip"
sColorName[28] = "Moccasin"
sColorName[29] = "PeachPuff"
sColorName[30] = "PaleGoldenrod"
sColorName[31] = "Khaki"
sColorName[32] = "DarkKhaki"

sColorFamily[5] = "Purple Colors"
iColorFast[5] = 33
iColorLast[5] = 50
sColorName[33] = "Lavender"
sColorName[34] = "Thistle"
sColorName[35] = "Plum"
sColorName[36] = "Violet"
sColorName[37] = "Orchid"
sColorName[38] = "Fuchsia"
sColorName[39] = "Magenta"
sColorName[40] = "MediumOrchid"
sColorName[41] = "MediumPurple"
sColorName[42] = "BlueViolet"
sColorName[43] = "DarkViolet"
sColorName[44] = "DarkOrchid"
sColorName[45] = "DarkMagenta"
sColorName[46] = "Purple"
sColorName[47] = "Indigo"
sColorName[48] = "SlateBlue"
sColorName[49] = "DarkSlateBlue"
sColorName[50] = "MediumSlateBlue"

sColorFamily[6] = "Green Colors"
iColorFast[6] = 51
iColorLast[6] = 73
sColorName[51] = "GreenYellow"
sColorName[52] = "Chartreuse"
sColorName[53] = "LawnGreen"
sColorName[54] = "Lime"
sColorName[55] = "LimeGreen"
sColorName[56] = "PaleGreen"
sColorName[57] = "LightGreen"
sColorName[58] = "MediumSpringGreen"
sColorName[59] = "SpringGreen"
sColorName[60] = "MediumSeaGreen"
sColorName[61] = "SeaGreen"
sColorName[62] = "ForestGreen"
sColorName[63] = "Green"
sColorName[64] = "DarkGreen"
sColorName[65] = "YellowGreen"
sColorName[66] = "OliveDrab"
sColorName[67] = "Olive"
sColorName[68] = "DarkOliveGreen"
sColorName[69] = "MediumAquamarine"
sColorName[70] = "DarkSeaGreen"
sColorName[71] = "LightSeaGreen"
sColorName[72] = "DarkCyan"
sColorName[73] = "Teal"

sColorFamily[7] = "Blue Colors"
iColorFast[7] = 74
iColorLast[7] = 98
sColorName[74] = "Aqua"
sColorName[75] = "Cyan"
sColorName[76] = "LightCyan"
sColorName[77] = "PaleTurquoise"
sColorName[78] = "Aquamarine"
sColorName[79] = "Turquoise"
sColorName[80] = "MediumTurquoise"
sColorName[81] = "DarkTurquoise"
sColorName[82] = "CadetBlue"
sColorName[83] = "SteelBlue"
sColorName[84] = "LightSteelBlue"
sColorName[85] = "PowderBlue"
sColorName[86] = "LightBlue"
sColorName[87] = "SkyBlue"
sColorName[88] = "LightSkyBlue"
sColorName[89] = "DeepSkyBlue"
sColorName[90] = "DodgerBlue"
sColorName[91] = "CornflowerBlue"
sColorName[92] = "MediumSlateBlue"
sColorName[93] = "RoyalBlue"
sColorName[94] = "Blue"
sColorName[95] = "MediumBlue"
sColorName[96] = "DarkBlue"
sColorName[97] = "Navy"
sColorName[98] = "MidnightBlue"

sColorFamily[8] = "Brown Colors"
iColorFast[8] = 99
iColorLast[8] = 115
sColorName[99] = "Cornsilk"
sColorName[100] = "BlanchedAlmond"
sColorName[101] = "Bisque"
sColorName[102] = "NavajoWhite"
sColorName[103] = "Wheat"
sColorName[104] = "BurlyWood"
sColorName[105] = "Tan"
sColorName[106] = "RosyBrown"
sColorName[107] = "SandyBrown"
sColorName[108] = "Goldenrod"
sColorName[109] = "DarkGoldenrod"
sColorName[110] = "Peru"
sColorName[111] = "Chocolate"
sColorName[112] = "SaddleBrown"
sColorName[113] = "Sienna"
sColorName[114] = "Brown"
sColorName[115] = "Maroon"

sColorFamily[9] = "White Colors"
iColorFast[9] = 116
iColorLast[9] = 132
sColorName[116] = "White"
sColorName[117] = "Snow"
sColorName[118] = "Honeydew"
sColorName[119] = "MintCream"
sColorName[120] = "Azure"
sColorName[121] = "AliceBlue"
sColorName[122] = "GhostWhite"
sColorName[123] = "WhiteSmoke"
sColorName[124] = "Seashell"
sColorName[125] = "Beige"
sColorName[126] = "OldLace"
sColorName[127] = "FloralWhite"
sColorName[128] = "Ivory"
sColorName[129] = "AntiqueWhite"
sColorName[130] = "Linen"
sColorName[131] = "LavenderBlush"
sColorName[132] = "MistyRose"

sColorFamily[10] = "Gray Colors"
iColorFast[10] = 133
iColorLast[10] = 142
sColorName[133] = "Gainsboro"
sColorName[134] = "LightGray"
sColorName[135] = "Silver"
sColorName[136] = "DarkGray"
sColorName[137] = "Gray"
sColorName[138] = "DimGray"
sColorName[139] = "LightSlateGray"
sColorName[140] = "SlateGray"
sColorName[141] = "DarkSlateGray"
sColorName[142] = "Black"
EndSub

' Color pick | Initialize
Sub ColorPick_Init
GraphicsWindow.PenColor = "Gray"
GraphicsWindow.BrushColor = "White"
oRect = Shapes.AddRectangle(70, 67)
Shapes.HideShape(oRect)
GraphicsWindow.BrushColor = "Black"
oText = Shapes.AddText("")
Shapes.HideShape(oText)
EndSub

' Color pick | Show
Sub ColorPick_Show
iMX = GraphicsWindow.MouseX
iMY = GraphicsWindow.MouseY
Shapes.Move(oRect, iMX + 10, iMY + 10)
Shapes.Move(oText, iMX + 14, iMY + 14)
sRGB = GraphicsWindow.GetPixel(iMX, iMY)
Shapes.SetText(oText, sRGB)
Shapes.ShowShape(oRect)
Shapes.ShowShape(oText)
GraphicsWindow.MouseMove = ColorPick_OnMouseMove
EndSub

' Color pick | On mouse move
Sub ColorPick_OnMouseMove
iMX = GraphicsWindow.MouseX
iMY = GraphicsWindow.MouseY
bMouseMoved = "True"
EndSub

' Math | Convert hexadecimal to decimal
' in: sHex
' out: iDec
Sub Math_Hex2Dec
iDec = 0
iLen = Text.GetLength(sHex)
For iPtr = 1 To iLen
iDec = iDec * 16 + Text.GetIndexOf("0123456789ABCDEF", Text.GetSubText(sHex, iPtr, 1)) - 1
EndFor
EndSub