# colormodel.py # Walker M. White (wmw2) # August 6, 2015 """Classes for three different color models. The classes are RGB, CMYK, HSV. The constants in this module are all defined in the RGB color space. In addition, this module has support for converting values into the the TKinter color space.""" import colorsys # To handle round off error _epsilon = 1e-13 class RGB(object): """An instance is a RGB color value.""" # MUTABLE ATTRIBUTES @property def red(self): """The red channel. **Invariant**: Value must be an int between 0 and 255, inclusive.""" return self._red @red.setter def red(self, value): assert (type(value) == int), "value %s is not an int" % `value` assert (value >= 0 and value <= 255), "value %s is outside of range [0,255]" % `value` self._red = value @red.deleter def red(self): del self._red @property def green(self): """The green channel. **Invariant**: Value must be an int between 0 and 255, inclusive.""" return self._green @green.setter def green(self, value): assert (type(value) == int), "value %s is not an int" % `value` assert (value >= 0 and value <= 255), "value %s is outside of range [0,255]" % `value` self._green = value @green.deleter def green(self): del self._green @property def blue(self): """The blue channel. **Invariant**: Value must be an int between 0 and 255, inclusive.""" return self._blue @blue.setter def blue(self, value): assert (type(value) == int), "value %s is not an int" % `value` assert (value >= 0 and value <= 255), "value %s is outside of range [0,255]" % `value` self._blue = value @blue.deleter def blue(self): del self._blue @property def alpha(self): """The alpha channel. Used for transparency effects (but not in this course). **Invariant**: Value must be an int between 0 and 255, inclusive.""" return self._alpha @alpha.setter def alpha(self, value): assert (type(value) == int), "value %s is not an int" % `value` assert (value >= 0 and value <= 255), "value %s is outside of range [0,255]" % `value` self._alpha = value @alpha.deleter def alpha(self): del self._alpha # BUILT-IN METHODS def __init__(self, r, g, b, a=255): """**Constructor**: creates a new RGB value (r,g,b,a). :param r: initial red value **Precondition**: int between 0 and 255, inclusive. :param g: initial green value **Precondition**: int between 0 and 255, inclusive. :param b: initial blue value **Precondition**: int between 0 and 255, inclusive. :param a: initial alpha value (default 255) **Precondition**: int between 0 and 255, inclusive. The alpha channel is 255 by default, unless otherwise specified.""" self.red = r self.green = g self.blue = b self.alpha = a def __eq__(self, other): """**Returns**: True if self and other are equivalent RGB colors. """ return (type(other) == RGB and self.red == other.red and self.green == other.green and self.blue == other.blue and self.alpha == other.alpha) def __ne__(self, other): """**Returns**: True if self and other are not equivalent RGB colors. """ return (type(other) != RGB or self.red != other.red or self.green != other.green or self.blue != other.blue or self.alpha != other.alpha) def __str__(self): """**Returns**: A readable string representation of this color. """ return "("+str(self.red)+","+str(self.green)+","+str(self.blue)+","+str(self.alpha)+")" def __repr__(self): """**Returns**: An unambiguous String representation of this color. """ return "(red="+str(self.red)+",green="+str(self.green)+",blue="+str(self.blue)+",alpha="+str(self.alpha)+")" # PUBLIC METHODS def glColor(self): """**Returns**: a 4 element list of the attributes in the range 0 to 1 This is a conversion of this object into a format that can be used in openGL graphics""" return [self.red/255.0, self.green/255.0, self.blue/255.0, self.alpha/255.0] def tkColor(self): """**Returns**: a 3 element tuple of the attributes in the range 0 to 1 This is a conversion of this object into a format that can be used by Tkinter (e.g. the drawing turtle).""" return (self.red/255.0, self.green/255.0, self.blue/255.0) # CLASS METHODS FOR TKinter SUPPORT @classmethod def CreateName(cls,name): """Creates a new RGB object with the given color name. Color name conversion is handled by the standard RGB color space. :param name: the color name **Precondition**: name is a valid tkinter color name """ assert name in _TK_COLOR_MAP, "parameter %s is not a valid color name" % `name` return cls.CreateWebColor(_TK_COLOR_MAP[name]) @classmethod def CreateWebColor(cls,color): """Creates a new RGB object from the given web color string. A web color string is a 6-digit hexadecimal string starting with a hashtag (#). It does not include an alpha value. :param color: the web color **Precondition**: color is a valid web color string """ assert type(color) == str, "paramter %s is not a string" % `color` assert color[0] == '#' and len(color) == 7, "paramter % is not a valid web color" % `color` try: red = int(color[1:3],16) except: assert false, "red value %s is out of range" % `color[1:3]` try: green = int(color[3:5],16) except: assert false, "green value %s is out of range" % `color[3:5]` try: blue = int(color[5:7],16) except: assert false, "green value %s is out of range" % `color[5:7]` return cls(red,green,blue) class CMYK(object): """An instance is a CMYK color value.""" # MUTABLE ATTRIBUTES @property def cyan(self): """The cyan channel. **Invariant**: Value must be a float between 0.0 and 100.0, inclusive.""" return self._cyan @cyan.setter def cyan(self, value): assert (type(value) == int or type(value) == float), "value %s is not a number" % `value` if (value > 100.0): value = min(value,100.0) if value < 100.0+_epsilon else value if (value < 0.0): value = max(value,0.0) if value > -_epsilon else value assert (value >= 0.0 and value <= 100.0), "value %s is outside of range [0.0,100.0]" % `value` self._cyan = float(value) @cyan.deleter def cyan(self): del self._cyan @property def magenta(self): """The magenta channel. **Invariant**: Value must be a float between 0.0 and 100.0, inclusive.""" return self._magenta @magenta.setter def magenta(self, value): assert (type(value) == int or type(value) == float), "value %s is not a number" % `value` if (value > 100.0): value = min(value,100.0) if value < 100.0+_epsilon else value if (value < 0.0): value = max(value,0.0) if value > -_epsilon else value assert (value >= 0.0 and value <= 100.0), "value %s is outside of range [0.0,100.0]" % `value` self._magenta = float(value) @magenta.deleter def magenta(self): del self._magenta @property def yellow(self): """The yellow channel. **Invariant**: Value must be a float between 0.0 and 100.0, inclusive.""" return self._yellow @yellow.setter def yellow(self, value): assert (type(value) == int or type(value) == float), "value %s is not a number" % `value` if (value > 100.0): value = min(value,100.0) if value < 100.0+_epsilon else value if (value < 0.0): value = max(value,0.0) if value > -_epsilon else value assert (value >= 0.0 and value <= 100.0), "value %s is outside of range [0.0,100.0]" % `value` self._yellow = float(value) @yellow.deleter def yellow(self): del self._yellow @property def black(self): """The black channel. **Invariant**: Value must be a float between 0.0 and 100.0, inclusive.""" return self._black @black.setter def black(self, value): assert (type(value) == int or type(value) == float), "value %s is not a number" % `value` if (value > 100.0): value = min(value,100.0) if value < 100.0+_epsilon else value if (value < 0.0): value = max(value,0.0) if value > -_epsilon else value assert (value >= 0 and value <= 255), "value %s is outside of range [0,255]" % `value` self._black = float(value) @black.deleter def black(self): del self._black # BUILT-IN METHODS def __init__(self, c, m, y, k): """**Constructor**: creates a new CMYK color (c,m,y,k). :param c: initial cyan value **Precondition**: float between 0.0 and 100.0, inclusive. :param m: initial magenta value **Precondition**: float between 0.0 and 100.0, inclusive. :param y: initial yellow value **Precondition**: float between 0.0 and 100.0, inclusive. :param k: initial black value **Precondition**: float between 0.0 and 100.0, inclusive. No arguments are optional.""" self.cyan = c self.magenta = m self.yellow = y self.black = k def __eq__(self, other): """**Returns**: True if self and other are equivalent CMYK colors. """ return (type(other) == CMYK and self.cyan == other.cyan and self.magenta == other.magenta and self.yellow == other.yellow and self.black == other.black) def __ne__(self, other): """**Returns**: True if self and other are not equivalent CMYK colors. """ return (type(other) != CMYK or self.cyan != other.cyan or self.magenta != other.magenta or self.yellow != other.yellow or self.black != other.black) def __str__(self): """**Returns**: A readable String representation of this color. """ return "("+str(self.cyan)+","+str(self.magenta)+","+str(self.yellow)+","+str(self.black)+")" def __repr__(self): """**Returns**: An unambiguous String representation of this color. """ return "(cyan="+str(self.cyan)+",magenta="+str(self.magenta)+",yellow="+str(self.yellow)+",black="+str(self.black)+")" class HSV(object): """An instance is a HSV color value.""" # MUTABLE ATTRIBUTES @property def hue(self): """The hue channel. **Invariant**: Value must be a float between 0.0 and 360.0, not including 360.0.""" return self._hue @hue.setter def hue(self, value): assert (type(value) == int or type(value) == float), "value %s is not a number" % `value` if (value < 0.0): value = max(value,0.0) if value > -_epsilon else value assert (value >= 0.0 and value < 360.0), "value %s is outside of range [0.0,360.0)" % `value` self._hue = float(value) @hue.deleter def hue(self): del self._hue @property def saturation(self): """The staturation channel. **Invariant**: Value must be a float between 0.0 and 1.0, inclusive.""" return self._saturation @saturation.setter def saturation(self, value): assert (type(value) == int or type(value) == float), "value %s is not a number" % `value` if (value > 1.0): value = min(value,1.0) if value < 1.0+_epsilon else value if (value < 0.0): value = max(value,0.0) if value > -_epsilon else value assert (value >= 0.0 and value <= 1.0), "value %s is outside of range [0.0,1.0]" % `value` self._saturation = float(value) @saturation.deleter def saturation(self): del self._saturation @property def value(self): """The value channel. **Invariant**: Value must be a float between 0.0 and 1.0, inclusive.""" return self._value @value.setter def value(self, val): assert (type(val) == int or type(val) == float), "value %s is not a number" % `val` if (val > 1.0): val = min(val,1.0) if value < 1.0+_epsilon else val if (val < 0.0): val = max(val,0.0) if value > -_epsilon else val assert (val >= 0.0 and val <= 1.0), "value %s is outside of range [0.0,1.0]" % `val` self._value = float(val) @value.deleter def value(self): del self._value # BUILT-IN METHODS def __init__(self, h, s, v): """**Constructor**: creates a new HSV color (h,s,v). :param h: the initial hue **Precondition**: float between 0.0 and 360.0, not including including 360.0. :param s: the initial saturation **Precondition**: float between 0.0 and 1.0, inclusive. :param v: the initial value **Precondition**: float between 0.0 and 1.0, inclusive. No arguments are optional.""" self.hue = h self.saturation = s self.value = v def __eq__(self, other): """**Returns**: True if self and other are equivalent HSV colors. """ return (type(other) == HSV and self.hue == other.hue and self.saturation == other.saturation and self.value == other.value) def __ne__(self, other): """**Returns**: True if self and other are equivalent HSV colors. """ return (type(other) != HSV or self.hue != other.hue or self.saturation != other.saturation or self.value != other.value) def __str__(self): """**Returns**: A readable String representation of this color. """ return "("+str(self.hue)+","+str(self.saturation)+","+str(self.value)+")" def __repr__(self): """**Returns**: An unambiguous String representation of this color. """ return "(hue="+str(self.hue)+",saturation="+str(self.saturation)+",value="+str(self.value)+")" # PUBLIC METHODS def glColor(self): """**Returns**: a 4 element list of the equivalent rgba color. This method converts this object to an RGB object and then extracts a 4 element list with color values between 0 and 1. This is a conversion of this object into a format that can be used in openGL graphics""" rgb = colorsys.hsv_to_rgb(self.hue/360.0,self.saturation,self.value) return [rgb[0], rgb[1], rgb[2], 1.0] def tkColor(self): """**Returns**: a 3 element tuple of the equivalent rgb color. This method converts this object to an RGB object and then extracts a 3 element tuple with color values between 0 and 1. This is a conversion of this object into a format that can be used by the drawing turtle""" return colorsys.hsv_to_rgb(self.hue/360.0,self.saturation,self.value) # COLOR CONSTANTS #: The color white in the default sRGB space. WHITE = RGB(255, 255, 255) #: The color light gray in the default sRGB space. LIGHT_GRAY = RGB(192, 192, 192) #: The color gray in the default sRGB space. GRAY = RGB(128, 128, 128) #: The color dark gray in the default sRGB space. DARK_GRAY = RGB(64, 64, 64) #: The color black in the default sRGB space. BLACK = RGB(0, 0, 0) #: The color red, in the default sRGB space. RED = RGB(255, 0, 0) #: The color pink in the default sRGB space. PINK = RGB(255, 175, 175) #: The color orange in the default sRGB space. ORANGE = RGB(255, 200, 0) #: The color yellow in the default sRGB space. YELLOW = RGB(255, 255, 0) #: The color green in the default sRGB space. GREEN = RGB(0, 255, 0); #: The color magenta in the default sRGB space. MAGENTA = RGB(255, 0, 255) #: The color cyan in the default sRGB space. CYAN = RGB(0, 255, 255) #: The color blue in the default sRGB space. BLUE = RGB(0, 0, 255) # TKinter COLOR SUPPORT # Unfortunately, this had to be done manually. _TK_COLOR_MAP = { 'alice blue': '#F0F8FF', 'AliceBlue' : '#F0F8FF', 'antique white': '#FAEBD7', 'AntiqueWhite': '#FAEBD7', 'AntiqueWhite1': '#FFEFDB', 'AntiqueWhite2': '#EEDFCC', 'AntiqueWhite3': '#CDC0B0', 'AntiqueWhite4': '#8B8378', 'aquamarine': '#7FFFD4', 'aquamarine1': '#7FFFD4', 'aquamarine2': '#76EEC6', 'aquamarine3': '#66CDAA', 'aquamarine4': '#458B74', 'azure': '#F0FFFF', 'azure1': '#F0FFFF', 'azure2': '#E0EEEE', 'azure3': '#C1CDCD', 'azure4': '#838B8B', 'beige': '#F5F5DC', 'bisque': '#FFE4C4', 'bisque1': '#FFE4C4', 'bisque2': '#EED5B7', 'bisque3': '#CDB79E', 'bisque4': '#8B7D6B', 'black': '#000000', 'blanched almond': '#FFEBCD', 'BlanchedAlmond': '#FFEBCD', 'blue': '#0000FF', 'blue violet': '#8A2BE2', 'blue1': '#0000FF', 'blue2': '#0000EE', 'blue3': '#0000CD', 'blue4': '#00008B', 'BlueViolet': '#8A2BE2', 'brown': '#A52A2A', 'brown1': '#FF4040', 'brown2': '#EE3B3B', 'brown3': '#CD3333', 'brown4': '#8B2323', 'burlywood': '#DEB887', 'burlywood1': '#FFD39B', 'burlywood2': '#EEC591', 'burlywood3': '#CDAA7D', 'burlywood4': '#8B7355', 'cadet blue': '#5F9EA0', 'CadetBlue': '#5F9EA0', 'CadetBlue1': '#98F5FF', 'CadetBlue2': '#8EE5EE', 'CadetBlue3': '#7AC5CD', 'CadetBlue4': '#53868B', 'chartreuse': '#7FFF00', 'chartreuse1': '#7FFF00', 'chartreuse2': '#76EE00', 'chartreuse3': '#66CD00', 'chartreuse4': '#458B00', 'chocolate': '#D2691E', 'chocolate1': '#FF7F24', 'chocolate2': '#EE7621', 'chocolate3': '#CD661D', 'chocolate4': '#8B4513', 'coral': '#FF7F50', 'coral1': '#FF7256', 'coral2': '#EE6A50', 'coral3': '#CD5B45', 'coral4': '#8B3E2F', 'cornflower blue': '#6495ED', 'CornflowerBlue': '#6495ED', 'cornsilk': '#FFF8DC', 'cornsilk1': '#FFF8DC', 'cornsilk2': '#EEE8CD', 'cornsilk3': '#CDC8B1', 'cornsilk4': '#8B8878', 'cyan': '#00FFFF', 'cyan1': '#00FFFF', 'cyan2': '#00EEEE', 'cyan3': '#00CDCD', 'cyan4': '#008B8B', 'dark blue': '#00008B', 'dark cyan': '#008B8B', 'dark goldenrod': '#B8860B', 'dark gray': '#A9A9A9', 'dark green': '#006400', 'dark grey': '#A9A9A9', 'dark khaki': '#BDB76B', 'dark magenta': '#8B008B', 'dark olive green': '#556B2F', 'dark orange': '#FF8C00', 'dark orchid': '#9932CC', 'dark red': '#8B0000', 'dark salmon': '#E9967A', 'dark sea green': '#8FBC8F', 'dark slate blue': '#483D8B', 'dark slate gray': '#2F4F4F', 'dark slate grey': '#2F4F4F', 'dark turquoise': '#00CED1', 'dark violet': '#9400D3', 'DarkBlue': '#00008B', 'DarkCyan': '#008B8B', 'DarkGoldenrod': '#B8860B', 'DarkGoldenrod1': '#FFB90F', 'DarkGoldenrod2': '#EEAD0E', 'DarkGoldenrod3': '#CD950C', 'DarkGoldenrod4': '#8B6508', 'DarkGray': '#A9A9A9', 'DarkGreen': '#006400', 'DarkGrey': '#A9A9A9', 'DarkKhaki': '#BDB76B', 'DarkMagenta': '#8B008B', 'DarkOliveGreen': '#556B2F', 'DarkOliveGreen1': '#CAFF70', 'DarkOliveGreen2': '#BCEE68', 'DarkOliveGreen3': '#A2CD5A', 'DarkOliveGreen4': '#6E8B3D', 'DarkOrange': '#FF8C00', 'DarkOrange1': '#FF7F00', 'DarkOrange2': '#EE7600', 'DarkOrange3': '#CD6600', 'DarkOrange4': '#8B4500', 'DarkOrchid': '#9932CC', 'DarkOrchid1': '#BF3EFF', 'DarkOrchid2': '#B23AEE', 'DarkOrchid3': '#9A32CD', 'DarkOrchid4': '#68228B', 'DarkRed': '#8B0000', 'DarkSalmon': '#E9967A', 'DarkSeaGreen': '#8FBC8F', 'DarkSeaGreen1': '#C1FFC1', 'DarkSeaGreen2': '#B4EEB4', 'DarkSeaGreen3': '#9BCD9B', 'DarkSeaGreen4': '#698B69', 'DarkSlateBlue': '#483D8B', 'DarkSlateGray': '#2F4F4F', 'DarkSlateGray1': '#97FFFF', 'DarkSlateGray2': '#8DEEEE', 'DarkSlateGray3': '#79CDCD', 'DarkSlateGray4': '#528B8B', 'DarkSlateGrey': '#2F4F4F', 'DarkTurquoise': '#00CED1', 'DarkViolet': '#9400D3', 'deep pink': '#FF1493', 'deep sky blue': '#00BFFF', 'DeepPink': '#FF1493', 'DeepPink1': '#FF1493', 'DeepPink2': '#EE1289', 'DeepPink3': '#CD1076', 'DeepPink4': '#8B0A50', 'DeepSkyBlue': '#00BFFF', 'DeepSkyBlue1': '#00BFFF', 'DeepSkyBlue2': '#00B2EE', 'DeepSkyBlue3': '#009ACD', 'DeepSkyBlue4': '#00688B', 'dim gray': '#696969', 'dim grey': '#696969', 'DimGray': '#696969', 'DimGrey': '#696969', 'dodger blue': '#1E90FF', 'DodgerBlue': '#1E90FF', 'DodgerBlue1': '#1E90FF', 'DodgerBlue2': '#1C86EE', 'DodgerBlue3': '#1874CD', 'DodgerBlue4': '#104E8B', 'firebrick': '#B22222', 'firebrick1': '#FF3030', 'firebrick2': '#EE2C2C', 'firebrick3': '#CD2626', 'firebrick4': '#8B1A1A', 'floral white': '#FFFAF0', 'FloralWhite': '#FFFAF0', 'forest green': '#228B22', 'ForestGreen': '#228B22', 'gainsboro': '#DCDCDC', 'ghost white': '#F8F8FF', 'GhostWhite': '#F8F8FF', 'gold': '#FFD700', 'gold1': '#FFD700', 'gold2': '#EEC900', 'gold3': '#CDAD00', 'gold4': '#8B7500', 'goldenrod': '#DAA520', 'goldenrod1': '#FFC125', 'goldenrod2': '#EEB422', 'goldenrod3': '#CD9B1D', 'goldenrod4': '#8B6914', 'gray': '#BEBEBE', 'gray0': '#000000', 'gray1': '#030303', 'gray2': '#050505', 'gray3': '#080808', 'gray4': '#0A0A0A', 'gray5': '#0D0D0D', 'gray6': '#0F0F0F', 'gray7': '#121212', 'gray8': '#141414', 'gray9': '#171717', 'gray10': '#1A1A1A', 'gray11': '#1C1C1C', 'gray12': '#1F1F1F', 'gray13': '#212121', 'gray14': '#242424', 'gray15': '#262626', 'gray16': '#292929', 'gray17': '#2B2B2B', 'gray18': '#2E2E2E', 'gray19': '#303030', 'gray20': '#333333', 'gray21': '#363636', 'gray22': '#383838', 'gray23': '#3B3B3B', 'gray24': '#3D3D3D', 'gray25': '#404040', 'gray26': '#424242', 'gray27': '#454545', 'gray28': '#474747', 'gray29': '#4A4A4A', 'gray30': '#4D4D4D', 'gray31': '#4F4F4F', 'gray32': '#525252', 'gray33': '#545454', 'gray34': '#575757', 'gray35': '#595959', 'gray36': '#5C5C5C', 'gray37': '#5E5E5E', 'gray38': '#616161', 'gray39': '#636363', 'gray40': '#666666', 'gray41': '#696969', 'gray42': '#6B6B6B', 'gray43': '#6E6E6E', 'gray44': '#707070', 'gray45': '#737373', 'gray46': '#757575', 'gray47': '#787878', 'gray48': '#7A7A7A', 'gray49': '#7D7D7D', 'gray50': '#7F7F7F', 'gray51': '#828282', 'gray52': '#858585', 'gray53': '#878787', 'gray54': '#8A8A8A', 'gray55': '#8C8C8C', 'gray56': '#8F8F8F', 'gray57': '#919191', 'gray58': '#949494', 'gray59': '#969696', 'gray60': '#999999', 'gray61': '#9C9C9C', 'gray62': '#9E9E9E', 'gray63': '#A1A1A1', 'gray64': '#A3A3A3', 'gray65': '#A6A6A6', 'gray66': '#A8A8A8', 'gray67': '#ABABAB', 'gray68': '#ADADAD', 'gray69': '#B0B0B0', 'gray70': '#B3B3B3', 'gray71': '#B5B5B5', 'gray72': '#B8B8B8', 'gray73': '#BABABA', 'gray74': '#BDBDBD', 'gray75': '#BFBFBF', 'gray76': '#C2C2C2', 'gray77': '#C4C4C4', 'gray78': '#C7C7C7', 'gray79': '#C9C9C9', 'gray80': '#CCCCCC', 'gray81': '#CFCFCF', 'gray82': '#D1D1D1', 'gray83': '#D4D4D4', 'gray84': '#D6D6D6', 'gray85': '#D9D9D9', 'gray86': '#DBDBDB', 'gray87': '#DEDEDE', 'gray88': '#E0E0E0', 'gray89': '#E3E3E3', 'gray90': '#E5E5E5', 'gray91': '#E8E8E8', 'gray92': '#EBEBEB', 'gray93': '#EDEDED', 'gray94': '#F0F0F0', 'gray95': '#F2F2F2', 'gray96': '#F5F5F5', 'gray97': '#F7F7F7', 'gray98': '#FAFAFA', 'gray99': '#FCFCFC', 'gray100': '#FFFFFF', 'green': '#00FF00', 'green yellow': '#ADFF2F', 'green1': '#00FF00', 'green2': '#00EE00', 'green3': '#00CD00', 'green4': '#008B00', 'GreenYellow': '#ADFF2F', 'grey': '#BEBEBE', 'grey0': '#000000', 'grey1': '#030303', 'grey2': '#050505', 'grey3': '#080808', 'grey4': '#0A0A0A', 'grey5': '#0D0D0D', 'grey6': '#0F0F0F', 'grey7': '#121212', 'grey8': '#141414', 'grey9': '#171717', 'grey10': '#1A1A1A', 'grey11': '#1C1C1C', 'grey12': '#1F1F1F', 'grey13': '#212121', 'grey14': '#242424', 'grey15': '#262626', 'grey16': '#292929', 'grey17': '#2B2B2B', 'grey18': '#2E2E2E', 'grey19': '#303030', 'grey20': '#333333', 'grey21': '#363636', 'grey22': '#383838', 'grey23': '#3B3B3B', 'grey24': '#3D3D3D', 'grey25': '#404040', 'grey26': '#424242', 'grey27': '#454545', 'grey28': '#474747', 'grey29': '#4A4A4A', 'grey30': '#4D4D4D', 'grey31': '#4F4F4F', 'grey32': '#525252', 'grey33': '#545454', 'grey34': '#575757', 'grey35': '#595959', 'grey36': '#5C5C5C', 'grey37': '#5E5E5E', 'grey38': '#616161', 'grey39': '#636363', 'grey40': '#666666', 'grey41': '#696969', 'grey42': '#6B6B6B', 'grey43': '#6E6E6E', 'grey44': '#707070', 'grey45': '#737373', 'grey46': '#757575', 'grey47': '#787878', 'grey48': '#7A7A7A', 'grey49': '#7D7D7D', 'grey50': '#7F7F7F', 'grey51': '#828282', 'grey52': '#858585', 'grey53': '#878787', 'grey54': '#8A8A8A', 'grey55': '#8C8C8C', 'grey56': '#8F8F8F', 'grey57': '#919191', 'grey58': '#949494', 'grey59': '#969696', 'grey60': '#999999', 'grey61': '#9C9C9C', 'grey62': '#9E9E9E', 'grey63': '#A1A1A1', 'grey64': '#A3A3A3', 'grey65': '#A6A6A6', 'grey66': '#A8A8A8', 'grey67': '#ABABAB', 'grey68': '#ADADAD', 'grey69': '#B0B0B0', 'grey70': '#B3B3B3', 'grey71': '#B5B5B5', 'grey72': '#B8B8B8', 'grey73': '#BABABA', 'grey74': '#BDBDBD', 'grey75': '#BFBFBF', 'grey76': '#C2C2C2', 'grey77': '#C4C4C4', 'grey78': '#C7C7C7', 'grey79': '#C9C9C9', 'grey80': '#CCCCCC', 'grey81': '#CFCFCF', 'grey82': '#D1D1D1', 'grey83': '#D4D4D4', 'grey84': '#D6D6D6', 'grey85': '#D9D9D9', 'grey86': '#DBDBDB', 'grey87': '#DEDEDE', 'grey88': '#E0E0E0', 'grey89': '#E3E3E3', 'grey90': '#E5E5E5', 'grey91': '#E8E8E8', 'grey92': '#EBEBEB', 'grey93': '#EDEDED', 'grey94': '#F0F0F0', 'grey95': '#F2F2F2', 'grey96': '#F5F5F5', 'grey97': '#F7F7F7', 'grey98': '#FAFAFA', 'grey99': '#FCFCFC', 'grey100': '#FFFFFF', 'honeydew': '#F0FFF0', 'honeydew1': '#F0FFF0', 'honeydew2': '#E0EEE0', 'honeydew3': '#C1CDC1', 'honeydew4': '#838B83', 'hot pink': '#FF69B4', 'HotPink': '#FF69B4', 'HotPink1': '#FF6EB4', 'HotPink2': '#EE6AA7', 'HotPink3': '#CD6090', 'HotPink4': '#8B3A62', 'indian red': '#CD5C5C', 'IndianRed': '#CD5C5C', 'IndianRed1': '#FF6A6A', 'IndianRed2': '#EE6363', 'IndianRed3': '#CD5555', 'IndianRed4': '#8B3A3A', 'ivory': '#FFFFF0', 'ivory1': '#FFFFF0', 'ivory2': '#EEEEE0', 'ivory3': '#CDCDC1', 'ivory4': '#8B8B83', 'khaki': '#F0E68C', 'khaki1': '#FFF68F', 'khaki2': '#EEE685', 'khaki3': '#CDC673', 'khaki4': '#8B864E', 'lavender': '#E6E6FA', 'lavender blush': '#FFF0F5', 'LavenderBlush': '#FFF0F5', 'LavenderBlush1': '#FFF0F5', 'LavenderBlush2': '#EEE0E5', 'LavenderBlush3': '#CDC1C5', 'LavenderBlush4': '#8B8386', 'lawn green': '#7CFC00', 'LawnGreen': '#7CFC00', 'lemon chiffon': '#FFFACD', 'LemonChiffon': '#FFFACD', 'LemonChiffon1': '#FFFACD', 'LemonChiffon2': '#EEE9BF', 'LemonChiffon3': '#CDC9A5', 'LemonChiffon4': '#8B8970', 'light blue': '#ADD8E6', 'light coral': '#F08080', 'light cyan': '#E0FFFF', 'light goldenrod': '#EEDD82', 'light goldenrod yellow': '#FAFAD2', 'light gray': '#D3D3D3', 'light green': '#90EE90', 'light grey': '#D3D3D3', 'light pink': '#FFB6C1', 'light salmon': '#FFA07A', 'light sea green': '#20B2AA', 'light sky blue': '#87CEFA', 'light slate blue': '#8470FF', 'light slate gray': '#778899', 'light slate grey': '#778899', 'light steel blue': '#B0C4DE', 'light yellow': '#FFFFE0', 'LightBlue': '#ADD8E6', 'LightBlue1': '#BFEFFF', 'LightBlue2': '#B2DFEE', 'LightBlue3': '#9AC0CD', 'LightBlue4': '#68838B', 'LightCoral': '#F08080', 'LightCyan': '#E0FFFF', 'LightCyan1': '#E0FFFF', 'LightCyan2': '#D1EEEE', 'LightCyan3': '#B4CDCD', 'LightCyan4': '#7A8B8B', 'LightGoldenrod': '#EEDD82', 'LightGoldenrod1': '#FFEC8B', 'LightGoldenrod2': '#EEDC82', 'LightGoldenrod3': '#CDBE70', 'LightGoldenrod4': '#8B814C', 'LightGoldenrodYellow': '#FAFAD2', 'LightGray': '#D3D3D3', 'LightGreen': '#90EE90', 'LightGrey': '#D3D3D3', 'LightPink': '#FFB6C1', 'LightPink1': '#FFAEB9', 'LightPink2': '#EEA2AD', 'LightPink3': '#CD8C95', 'LightPink4': '#8B5F65', 'LightSalmon': '#FFA07A', 'LightSalmon1': '#FFA07A', 'LightSalmon2': '#EE9572', 'LightSalmon3': '#CD8162', 'LightSalmon4': '#8B5742', 'LightSeaGreen': '#20B2AA', 'LightSkyBlue': '#87CEFA', 'LightSkyBlue1': '#B0E2FF', 'LightSkyBlue2': '#A4D3EE', 'LightSkyBlue3': '#8DB6CD', 'LightSkyBlue4': '#607B8B', 'LightSlateBlue': '#8470FF', 'LightSlateGray': '#778899', 'LightSlateGrey': '#778899', 'LightSteelBlue': '#B0C4DE', 'LightSteelBlue1': '#CAE1FF', 'LightSteelBlue2': '#BCD2EE', 'LightSteelBlue3': '#A2B5CD', 'LightSteelBlue4': '#6E7B8B', 'LightYellow': '#FFFFE0', 'LightYellow1': '#FFFFE0', 'LightYellow2': '#EEEED1', 'LightYellow3': '#CDCDB4', 'LightYellow4': '#8B8B7A', 'lime green': '#32CD32', 'LimeGreen': '#32CD32', 'linen': '#FAF0E6', 'magenta': '#FF00FF', 'magenta1': '#FF00FF', 'magenta2': '#EE00EE', 'magenta3': '#CD00CD', 'magenta4': '#8B008B', 'maroon': '#B03060', 'maroon1': '#FF34B3', 'maroon2': '#EE30A7', 'maroon3': '#CD2990', 'maroon4': '#8B1C62', 'medium aquamarine': '#66CDAA', 'medium blue': '#0000CD', 'medium orchid': '#BA55D3', 'medium purple': '#9370DB', 'medium sea green': '#3CB371', 'medium slate blue': '#7B68EE', 'medium spring green': '#00FA9A', 'medium turquoise': '#48D1CC', 'medium violet red': '#C71585', 'MediumAquamarine': '#66CDAA', 'MediumBlue': '#0000CD', 'MediumOrchid': '#BA55D3', 'MediumOrchid1': '#E066FF', 'MediumOrchid2': '#D15FEE', 'MediumOrchid3': '#B452CD', 'MediumOrchid4': '#7A378B', 'MediumPurple': '#9370DB', 'MediumPurple1': '#AB82FF', 'MediumPurple2': '#9F79EE', 'MediumPurple3': '#8968CD', 'MediumPurple4': '#5D478B', 'MediumSeaGreen': '#3CB371', 'MediumSlateBlue': '#7B68EE', 'MediumSpringGreen': '#00FA9A', 'MediumTurquoise': '#48D1CC', 'MediumVioletRed': '#C71585', 'midnight blue': '#191970', 'MidnightBlue': '#191970', 'mint cream': '#F5FFFA', 'MintCream': '#F5FFFA', 'misty rose': '#FFE4E1', 'MistyRose': '#FFE4E1', 'MistyRose1': '#FFE4E1', 'MistyRose2': '#EED5D2', 'MistyRose3': '#CDB7B5', 'MistyRose4': '#8B7D7B', 'moccasin': '#FFE4B5', 'navajo white': '#FFDEAD', 'NavajoWhite': '#FFDEAD', 'NavajoWhite1': '#FFDEAD', 'NavajoWhite2': '#EECFA1', 'NavajoWhite3': '#CDB38B', 'NavajoWhite4': '#8B795E', 'navy': '#000080', 'navy blue': '#000080', 'NavyBlue': '#000080', 'old lace': '#FDF5E6', 'OldLace': '#FDF5E6', 'olive drab': '#6B8E23', 'OliveDrab': '#6B8E23', 'OliveDrab1': '#C0FF3E', 'OliveDrab2': '#B3EE3A', 'OliveDrab3': '#9ACD32', 'OliveDrab4': '#698B22', 'orange': '#FFA500', 'orange red': '#FF4500', 'orange1': '#FFA500', 'orange2': '#EE9A00', 'orange3': '#CD8500', 'orange4': '#8B5A00', 'OrangeRed': '#FF4500', 'OrangeRed1': '#FF4500', 'OrangeRed2': '#EE4000', 'OrangeRed3': '#CD3700', 'OrangeRed4': '#8B2500', 'orchid': '#DA70D6', 'orchid1': '#FF83FA', 'orchid2': '#EE7AE9', 'orchid3': '#CD69C9', 'orchid4': '#8B4789', 'pale goldenrod': '#EEE8AA', 'pale green': '#98FB98', 'pale turquoise': '#AFEEEE', 'pale violet red': '#DB7093', 'PaleGoldenrod': '#EEE8AA', 'PaleGreen': '#98FB98', 'PaleGreen1': '#9AFF9A', 'PaleGreen2': '#90EE90', 'PaleGreen3': '#7CCD7C', 'PaleGreen4': '#548B54', 'PaleTurquoise': '#AFEEEE', 'PaleTurquoise1': '#BBFFFF', 'PaleTurquoise2': '#AEEEEE', 'PaleTurquoise3': '#96CDCD', 'PaleTurquoise4': '#668B8B', 'PaleVioletRed': '#DB7093', 'PaleVioletRed1': '#FF82AB', 'PaleVioletRed2': '#EE799F', 'PaleVioletRed3': '#CD687F', 'PaleVioletRed4': '#8B475D', 'papaya whip': '#FFEFD5', 'PapayaWhip': '#FFEFD5', 'peach puff': '#FFDAB9', 'PeachPuff': '#FFDAB9', 'PeachPuff1': '#FFDAB9', 'PeachPuff2': '#EECBAD', 'PeachPuff3': '#CDAF95', 'PeachPuff4': '#8B7765', 'peru': '#CD853F', 'pink': '#FFC0CB', 'pink1': '#FFB5C5', 'pink2': '#EEA9B8', 'pink3': '#CD919E', 'pink4': '#8B636C', 'plum': '#DDA0DD', 'plum1': '#FFBBFF', 'plum2': '#EEAEEE', 'plum3': '#CD96CD', 'plum4': '#8B668B', 'powder blue': '#B0E0E6', 'PowderBlue': '#B0E0E6', 'purple': '#A020F0', 'purple1': '#9B30FF', 'purple2': '#912CEE', 'purple3': '#7D26CD', 'purple4': '#551A8B', 'red': '#FF0000', 'red1': '#FF0000', 'red2': '#EE0000', 'red3': '#CD0000', 'red4': '#8B0000', 'rosy brown': '#BC8F8F', 'RosyBrown': '#BC8F8F', 'RosyBrown1': '#FFC1C1', 'RosyBrown2': '#EEB4B4', 'RosyBrown3': '#CD9B9B', 'RosyBrown4': '#8B6969', 'royal blue': '#4169E1', 'RoyalBlue': '#4169E1', 'RoyalBlue1': '#4876FF', 'RoyalBlue2': '#436EEE', 'RoyalBlue3': '#3A5FCD', 'RoyalBlue4': '#27408B', 'saddle brown': '#8B4513', 'SaddleBrown': '#8B4513', 'salmon': '#FA8072', 'salmon1': '#FF8C69', 'salmon2': '#EE8262', 'salmon3': '#CD7054', 'salmon4': '#8B4C39', 'sandy brown': '#F4A460', 'SandyBrown': '#F4A460', 'sea green': '#2E8B57', 'SeaGreen': '#2E8B57', 'SeaGreen1': '#54FF9F', 'SeaGreen2': '#4EEE94', 'SeaGreen3': '#43CD80', 'SeaGreen4': '#2E8B57', 'seashell': '#FFF5EE', 'seashell1': '#FFF5EE', 'seashell2': '#EEE5DE', 'seashell3': '#CDC5BF', 'seashell4': '#8B8682', 'sienna': '#A0522D', 'sienna1': '#FF8247', 'sienna2': '#EE7942', 'sienna3': '#CD6839', 'sienna4': '#8B4726', 'sky blue': '#87CEEB', 'SkyBlue': '#87CEEB', 'SkyBlue1': '#87CEFF', 'SkyBlue2': '#7EC0EE', 'SkyBlue3': '#6CA6CD', 'SkyBlue4': '#4A708B', 'slate blue': '#6A5ACD', 'slate gray': '#708090', 'slate grey': '#708090', 'SlateBlue': '#6A5ACD', 'SlateBlue1': '#836FFF', 'SlateBlue2': '#7A67EE', 'SlateBlue3': '#6959CD', 'SlateBlue4': '#473C8B', 'SlateGray': '#708090', 'SlateGray1': '#C6E2FF', 'SlateGray2': '#B9D3EE', 'SlateGray3': '#9FB6CD', 'SlateGray4': '#6C7B8B', 'SlateGrey': '#708090', 'snow': '#FFFAFA', 'snow1': '#FFFAFA', 'snow2': '#EEE9E9', 'snow3': '#CDC9C9', 'snow4': '#8B8989', 'spring green': '#00FF7F', 'SpringGreen': '#00FF7F', 'SpringGreen1': '#00FF7F', 'SpringGreen2': '#00EE76', 'SpringGreen3': '#00CD66', 'SpringGreen4': '#008B45', 'steel blue': '#4682B4', 'SteelBlue': '#4682B4', 'SteelBlue1': '#63B8FF', 'SteelBlue2': '#5CACEE', 'SteelBlue3': '#4F94CD', 'SteelBlue4': '#36648B', 'tan': '#D2B48C', 'tan1': '#FFA54F', 'tan2': '#EE9A49', 'tan3': '#CD853F', 'tan4': '#8B5A2B', 'thistle': '#D8BFD8', 'thistle1': '#FFE1FF', 'thistle2': '#EED2EE', 'thistle3': '#CDB5CD', 'thistle4': '#8B7B8B', 'tomato': '#FF6347', 'tomato1': '#FF6347', 'tomato2': '#EE5C42', 'tomato3': '#CD4F39', 'tomato4': '#8B3626', 'turquoise': '#40E0D0', 'turquoise1': '#00F5FF', 'turquoise2': '#00E5EE', 'turquoise3': '#00C5CD', 'turquoise4': '#00868B', 'violet': '#EE82EE', 'violet red': '#D02090', 'VioletRed': '#D02090', 'VioletRed1': '#FF3E96', 'VioletRed2': '#EE3A8C', 'VioletRed3': '#CD3278', 'VioletRed4': '#8B2252', 'wheat': '#F5DEB3', 'wheat1': '#FFE7BA', 'wheat2': '#EED8AE', 'wheat3': '#CDBA96', 'wheat4': '#8B7E66', 'white': '#FFFFFF', 'white smoke': '#F5F5F5', 'WhiteSmoke': '#F5F5F5', 'yellow': '#FFFF00', 'yellow green': '#9ACD32', 'yellow1': '#FFFF00', 'yellow2': '#EEEE00', 'yellow3': '#CDCD00', 'yellow4': '#8B8B00', 'YellowGreen': '#9ACD32', }