Difference between revisions of "VTK/Examples/Python/Visualization/NamedColorPatches"

From KitwarePublic
< VTK‎ | Examples‎ | Python
Jump to navigationJump to search
Line 32: Line 32:
  
 
It also shows how to select the text color based on luminance.
 
It also shows how to select the text color based on luminance.
In this case Digital CCIR601 is used which gives more weight to the
+
In this case Digital CCIR601 is used which gives less weight to the
 
  red and blue components of a color.
 
  red and blue components of a color.
 
We also create an auxiliary class called NamedColors, to facilitate the
 
interaction with the class vtkNamedColors.
 
  
 
'''
 
'''
Line 42: Line 39:
 
import vtk
 
import vtk
  
class NamedColors(object):
+
def RGBToHTMLColor(rgb):
 
+
     '''
     def __init__(self):
+
     Convert an [R, G, B] list to #RRGGBB.
        '''
+
     :param: rgb - The elements of the array rgb are unsigned chars (0..255).
            Define a single instance of the NamedColors class here.
+
     :return: The html color.
        '''
+
    '''
        self.namedColors = vtk.vtkNamedColors()
+
     hexcolor = "#"+ ''.join(map(lambda x: '{:02x}'.format(x),rgb))
 
+
    return hexcolor
     def GetRGBColor(self, colorName):
 
        '''
 
            Return the red, green and blue components for a
 
            color as doubles.
 
        '''
 
        rgb = [0.0, 0.0, 0.0] # black
 
        self.namedColors.GetColorRGB(colorName, rgb)
 
        return rgb
 
 
 
     def GetRGBColorInt(self, colorName):
 
        '''
 
            Return the red, green and blue components for a
 
            color as integer.
 
        '''
 
        return self.GetRGBAColorInt(colorName)[:3]
 
 
 
    def GetRGBAColor(self, colorName):
 
        '''
 
            Return the red, green, blue and alpha
 
            components for a color as doubles.
 
        '''
 
        rgba = [0.0, 0.0, 0.0, 1.0] # black
 
        self.namedColors.GetColor(colorName, rgba)
 
        return rgba
 
 
 
     def GetRGBAColorInt(self, colorName):
 
        '''
 
            Return the red, green, blue and alpha
 
            components for a color as integer.
 
        '''
 
        rgba = [int(0), int(0), int(0), int(255)] # black
 
        self.namedColors.GetColor(colorName, rgba)
 
        return rgba
 
 
 
    def GetColorNames(self):
 
        '''
 
            Return a list of color names.
 
        '''
 
        colorsNames = self.namedColors.GetColorNames()
 
        colorsNames = colorsNames.split('\n')
 
        return colorsNames
 
 
 
     def RGBToHTMLColor(self, rgb):
 
        '''
 
            Convert an [R, G, B] list to #RRGGBB.
 
        '''
 
        hexcolor = '#%02x%02x%02x' % tuple(rgb)
 
        # '%02x' means zero-padded, 2-digit hex values
 
        return hexcolor
 
 
 
    def HTMLColorToRGB(self, colorString):
 
        '''
 
            Convert #RRGGBB to a [R, G, B] list.
 
        '''
 
        colorString = colorString.strip()
 
        if colorString[0] == '#': colorString = colorString[1:]
 
        if len(colorString) != 6:
 
            raise ValueError, "Input #%s is not in #RRGGBB format" % colorString
 
        r, g, b = colorString[:2], colorString[2:4], colorString[4:]
 
        r, g, b = [int(n, 16) for n in (r, g, b)]
 
        return [r, g, b]
 
 
 
    def RGBToLumaCCIR601(self, rgb):
 
        '''
 
            RGB -> Luma conversion
 
            Digital CCIR601 (gives more weight to the R and B components)
 
        '''
 
        Y = 0.299 * rgb[0] + 0.587 * rgb[1] + 0.114 * rgb[2]
 
        return Y
 
 
 
  
    def GetSynonyms(self):
+
def HTMLColorToRGB(colorString):
        '''
+
    '''
            Return a list of synonyms.
+
    Convert #RRGGBB to a [R, G, B] list.
        '''
+
    :param: colorString a string in the form: #RRGGBB where RR, GG, BB are hexadecimal.
        syn = self.namedColors.GetSynonyms()
+
    The elements of the array rgb are unsigned chars (0..255).
        syn = syn.split('\n\n')
+
    :return: The red, green and blue components as a list.
         synonyms = []
+
    '''
        for ele in syn:
+
    colorString = colorString.strip()
            synonyms.append(ele.split('\n'))
+
    if colorString[0] == '#': colorString = colorString[1:]
        return synonyms
+
    if len(colorString) != 6:
 +
         raise ValueError, "Input #%s is not in #RRGGBB format" % colorString
 +
    r, g, b = colorString[:2], colorString[2:4], colorString[4:]
 +
    r, g, b = [int(n, 16) for n in (r, g, b)]
 +
    return [r, g, b]
  
    def FindSynonyms(self, colorName):
+
def RGBToLumaCCIR601(rgb):
        '''
+
    '''
            Find any synonyms for a specified color.
+
    RGB -> Luma conversion
        '''
+
    Digital CCIR601 (gives less weight to the R and B components)
        availableColors = self.GetColorNames()
+
    :param: rgb - The elements of the array rgb are unsigned chars (0..255).
        synonyms = []
+
    :return: The luminance.
        # We use lower case for comparison and
+
    '''
        # just the red, green, and blue components
+
    Y = 0.299 * rgb[0] + 0.587 * rgb[1] + 0.114 * rgb[2]
        # of the color.
+
    return Y
        lcolorName = colorName.lower()
 
        myColor = self.GetRGBColorInt(colorName)
 
        for color in availableColors:
 
            rgb = self.GetRGBColorInt(color)
 
            if myColor == rgb:
 
                synonyms.append(color)
 
        return synonyms
 
  
 +
def FormatRGBForHTML(rgb):
 +
    '''
 +
    Format the rgb colors for display on a html table.
 +
    :param: rgb - The elements of the array rgb are unsigned chars (0..255).
 +
    :return: A formatted string for the html table.
 +
    '''
 +
    s = ','.join(map(lambda x: '{:3d}'.format(x),rgb))
 +
    s = s.replace(' ','&#160;')
 +
    s = s.replace(',','&#160;&#160;')
 +
    return s
  
 
class MakeColorPatches(object):
 
class MakeColorPatches(object):
 
     def __init__(self):
 
     def __init__(self):
         self.cn = {'Red':['IndianRed', 'LightCoral', 'Salmon', 'DarkSalmon', 'LightSalmon', 'Red', 'Crimson', 'FireBrick', 'DarkRed'],
+
         self.cn = {
 +
            'Red':['IndianRed', 'LightCoral', 'Salmon', 'DarkSalmon', 'LightSalmon', 'Red', 'Crimson', 'FireBrick', 'DarkRed'],
 
             'Pink':['Pink', 'LightPink', 'HotPink', 'DeepPink', 'MediumVioletRed', 'PaleVioletRed'],
 
             'Pink':['Pink', 'LightPink', 'HotPink', 'DeepPink', 'MediumVioletRed', 'PaleVioletRed'],
 
             'Orange':['LightSalmon', 'Coral', 'Tomato', 'OrangeRed', 'DarkOrange', 'Orange'],
 
             'Orange':['LightSalmon', 'Coral', 'Tomato', 'OrangeRed', 'DarkOrange', 'Orange'],
Line 168: Line 103:
 
         self.cnEndTable = ['Purple', 'Blue/Cyan', 'Gray']
 
         self.cnEndTable = ['Purple', 'Blue/Cyan', 'Gray']
  
         self.vtkcn = {'Whites':['antique_white', 'azure', 'bisque', 'blanched_almond', 'cornsilk', 'eggshell', 'floral_white', 'gainsboro', 'ghost_white', 'honeydew', 'ivory', 'lavender', 'lavender_blush', 'lemon_chiffon', 'linen', 'mint_cream', 'misty_rose', 'moccasin', 'navajo_white', 'old_lace', 'papaya_whip', 'peach_puff', 'seashell', 'snow', 'thistle', 'titanium_white', 'wheat', 'white', 'white_smoke', 'zinc_white'],
+
         self.vtkcn = {
 +
            'Whites':['antique_white', 'azure', 'bisque', 'blanched_almond', 'cornsilk', 'eggshell', 'floral_white', 'gainsboro', 'ghost_white', 'honeydew', 'ivory', 'lavender', 'lavender_blush', 'lemon_chiffon', 'linen', 'mint_cream', 'misty_rose', 'moccasin', 'navajo_white', 'old_lace', 'papaya_whip', 'peach_puff', 'seashell', 'snow', 'thistle', 'titanium_white', 'wheat', 'white', 'white_smoke', 'zinc_white'],
 
             'Greys':['cold_grey', 'dim_grey', 'grey', 'light_grey', 'slate_grey', 'slate_grey_dark', 'slate_grey_light', 'warm_grey'],
 
             'Greys':['cold_grey', 'dim_grey', 'grey', 'light_grey', 'slate_grey', 'slate_grey_dark', 'slate_grey_light', 'warm_grey'],
 
             'Blacks':['black', 'ivory_black', 'lamp_black'],
 
             'Blacks':['black', 'ivory_black', 'lamp_black'],
Line 184: Line 120:
 
         self.vtkcnStartTable = ['Whites', 'Browns', 'Cyans']
 
         self.vtkcnStartTable = ['Whites', 'Browns', 'Cyans']
 
         self.vtkcnEndTable = ['Oranges', 'Greens', 'Magentas']
 
         self.vtkcnEndTable = ['Oranges', 'Greens', 'Magentas']
 +
        # The vtkNamedColors class.
 +
        self.nc = vtk.vtkNamedColors()
  
 
     def MakeHTMLHeader(self):
 
     def MakeHTMLHeader(self):
Line 192: Line 130:
 
         s += '<meta charset="UTF-8" />\n'
 
         s += '<meta charset="UTF-8" />\n'
 
         s += '</head>\n'
 
         s += '</head>\n'
 +
        return s
 +
 +
    def MakeHTMLIndex(self):
 +
        s = '<h2>Index</h2>\n'
 +
        s += '<ul>\n'
 +
        s += '\t<li><a href="#WebColorNames">Web color Names</li>\n'
 +
        s += '\t<li><a href="#VTKColorNames">VTK color Names</li>\n'
 +
        s += '\t<li><a href="#Synonyms">Synonyms</li>\n'
 +
        s += '</ul>\n'
 
         return s
 
         return s
  
Line 198: Line 145:
 
         s += '<th style="background:lightgrey">HTML name</th>\n'
 
         s += '<th style="background:lightgrey">HTML name</th>\n'
 
         s += '<th style="background:lightgrey">Decimal code<br />\n'
 
         s += '<th style="background:lightgrey">Decimal code<br />\n'
         s += 'R &#160; G &#160; B</th>\n'
+
         s += '&#160;&#160;R&#160;&#160;&#160;&#160;&#160;&#160;G&#160;&#160;&#160;&#160;&#160;&#160;B</th>\n'
 +
        s += '</tr>\n'
 +
        return s
 +
 
 +
    def MakeSynonymTableHeader(self):
 +
        s = '<tr>\n'
 +
        s += '<th style="background:lightgrey">Synonyms</th>\n'
 +
        s += '<th style="background:lightgrey">Decimal code<br />\n'
 +
        s += '&#160;&#160;R&#160;&#160;&#160;&#160;&#160;&#160;G&#160;&#160;&#160;&#160;&#160;&#160;B</th>\n'
 
         s += '</tr>\n'
 
         s += '</tr>\n'
 
         return s
 
         return s
Line 211: Line 166:
 
         s = '<tr>\n'
 
         s = '<tr>\n'
 
         s += '<td style="background:' + name + ';color:' + textColor + '">' + name + '</td>\n'
 
         s += '<td style="background:' + name + ';color:' + textColor + '">' + name + '</td>\n'
         s += '<td style="background:' + name + ';color:' + textColor + '"><tt>' + str(rgb[0]) + '&#160;&#160;' + str(rgb[1]) + '&#160;&#160;' + str(rgb[2]) + '</tt></td>\n'
+
         s += '<td style="background:' + name + ';color:' + textColor + '"><tt>' + FormatRGBForHTML(rgb) + '</tt></td>\n'
 
         s += '</tr>\n'
 
         s += '</tr>\n'
 
         return s
 
         return s
Line 218: Line 173:
 
         s = '<tr>\n'
 
         s = '<tr>\n'
 
         s += '<td style="background:' + nameColor + ';color:' + textColor + '">' + name + '</td>\n'
 
         s += '<td style="background:' + nameColor + ';color:' + textColor + '">' + name + '</td>\n'
         s += '<td style="background:' + nameColor + ';color:' + textColor + '"><tt>' + str(rgb[0]) + '&#160;&#160;' + str(rgb[1]) + '&#160;&#160;' + str(rgb[2]) + '</tt></td>\n'
+
         s += '<td style="background:' + nameColor + ';color:' + textColor + '"><tt>' + FormatRGBForHTML(rgb) + '</tt></td>\n'
 
         s += '</tr>\n'
 
         s += '</tr>\n'
 
         return s
 
         return s
Line 236: Line 191:
  
 
     def MakeWebColorTables(self):
 
     def MakeWebColorTables(self):
        colors = NamedColors()
 
 
         res = ''
 
         res = ''
 
         for key in self.cnOrder:
 
         for key in self.cnOrder:
Line 246: Line 200:
 
             values = self.cn[key]
 
             values = self.cn[key]
 
             for name in values:
 
             for name in values:
                 rgb = colors.GetRGBColorInt(name)
+
                 rgb = self.nc.GetColor3ub(name)
                 Y = colors.RGBToLumaCCIR601(rgb)
+
                 Y = RGBToLumaCCIR601(rgb)
 
                 textColor = '#000000' # Black
 
                 textColor = '#000000' # Black
 
                 if Y < 255 / 2.0:
 
                 if Y < 255 / 2.0:
Line 258: Line 212:
  
 
     def MakeVTKColorTables(self):
 
     def MakeVTKColorTables(self):
        colors = NamedColors()
 
 
         res = ''
 
         res = ''
 
         for key in self.vtkcnOrder:
 
         for key in self.vtkcnOrder:
Line 268: Line 221:
 
             values = self.vtkcn[key]
 
             values = self.vtkcn[key]
 
             for name in values:
 
             for name in values:
                 rgb = colors.GetRGBColorInt(name)
+
                 rgb = self.nc.GetColor3ub(name)
                 Y = colors.RGBToLumaCCIR601(rgb)
+
                 Y = RGBToLumaCCIR601(rgb)
 
                 textColor = '#000000' # Black
 
                 textColor = '#000000' # Black
 
                 if Y < 255 / 2.0:
 
                 if Y < 255 / 2.0:
 
                     textColor = '#ffffff' # White
 
                     textColor = '#ffffff' # White
                 nameColor = colors.RGBToHTMLColor(rgb)
+
                 nameColor = RGBToHTMLColor(rgb)
 
                 res += self.MakeVTKTR(name, nameColor, rgb, textColor)
 
                 res += self.MakeVTKTR(name, nameColor, rgb, textColor)
 
             if key in self.vtkcnEndTable:
 
             if key in self.vtkcnEndTable:
Line 281: Line 234:
  
 
     def MakeSynonymColorTable(self):
 
     def MakeSynonymColorTable(self):
         colors = NamedColors()
+
         syn = self.nc.GetSynonyms()
         synonyms = colors.GetSynonyms()
+
         # Convert to a list where each element is a list of the
 +
        #  color and its synonyms.
 +
        syn = syn.split('\n\n')
 +
        synonyms = []
 +
        for ele in syn:
 +
            synonyms.append(ele.split('\n'))
 
         cn = list()
 
         cn = list()
 
         for key, value in self.cn.iteritems():
 
         for key, value in self.cn.iteritems():
Line 292: Line 250:
 
         res = '<td>\n'
 
         res = '<td>\n'
 
         res += '<table>\n'
 
         res += '<table>\n'
         for colorNames in colors.GetSynonyms():
+
        res += self.MakeSynonymTableHeader()
 +
         for colorNames in synonyms: #colors.GetSynonyms():
 
             for idx, name in enumerate(colorNames):
 
             for idx, name in enumerate(colorNames):
 
                 if name in d:
 
                 if name in d:
 
                     colorNames[idx] = d[name]
 
                     colorNames[idx] = d[name]
             colorNames.sort()
+
             synonyms.sort()
 
             name = ", ".join(colorNames)
 
             name = ", ".join(colorNames)
             rgb = colors.GetRGBColorInt(colorNames[0])
+
             rgb = self.nc.GetColor3ub(colorNames[0])
             Y = colors.RGBToLumaCCIR601(rgb)
+
             Y = RGBToLumaCCIR601(rgb)
 
             textColor = '#000000' # Black
 
             textColor = '#000000' # Black
 
             if Y < 255 / 2.0:
 
             if Y < 255 / 2.0:
 
                 textColor = '#ffffff' # White
 
                 textColor = '#ffffff' # White
             nameColor = colors.RGBToHTMLColor(rgb)
+
             nameColor = RGBToHTMLColor(rgb)
 
             res += self.MakeVTKTR(name, nameColor, rgb, textColor)
 
             res += self.MakeVTKTR(name, nameColor, rgb, textColor)
 
         res += '</table>\n'
 
         res += '</table>\n'
Line 339: Line 298:
 
         res += '<h1>Synonyms in vtkNamedColors</h1>\n'
 
         res += '<h1>Synonyms in vtkNamedColors</h1>\n'
 
         res += '<table style="font-size:90%" cellpadding="4">\n'
 
         res += '<table style="font-size:90%" cellpadding="4">\n'
         res += '<caption style="background:lightgrey">Synonyms</caption>\n'
+
         res += '<caption style="background:lightgrey"></caption>\n'
 
         res += '<tr valign="top">\n'
 
         res += '<tr valign="top">\n'
 
         res += self.MakeSynonymColorTable()
 
         res += self.MakeSynonymColorTable()
Line 350: Line 309:
 
         res += '<body>\n'
 
         res += '<body>\n'
 
         res += '<h1>Colors available in vtkNamedColors</h1>\n'
 
         res += '<h1>Colors available in vtkNamedColors</h1>\n'
         res += '<p>The class vtkNamesColors provides color names and their values for the convenience of the user.</p>\n'
+
         res += '<p>The class vtkNamedColors provides color names and their values for the convenience of the user.</p>\n'
 
         res += '<p>The following tables show the available colors along with their red, green and blue values.</p>\n'
 
         res += '<p>The following tables show the available colors along with their red, green and blue values.</p>\n'
         res += '<h2>Web color Names</h2>'
+
        res += self.MakeHTMLIndex()
 +
         res += '<h2><a id="WebColorNames">Web color Names</h2>'
 
         res += 'These colors correspond to those in <a href="http://en.wikipedia.org/wiki/Web_colors" title="Web Colors">Web Colors</a>.\n'
 
         res += 'These colors correspond to those in <a href="http://en.wikipedia.org/wiki/Web_colors" title="Web Colors">Web Colors</a>.\n'
 
         res += '<table style="font-size:90%" cellpadding="4">\n'
 
         res += '<table style="font-size:90%" cellpadding="4">\n'
        res += '<caption style="background:lightgrey">Web Color Names</caption>\n'
 
 
         res += '<tr valign="top">\n'
 
         res += '<tr valign="top">\n'
 
         res += self.MakeWebColorTables()
 
         res += self.MakeWebColorTables()
 
         res += '</table>\n'
 
         res += '</table>\n'
         res += '<h2>VTK color Names</h2>'
+
         res += '<h2><a id="VTKColorNames">VTK color Names</h2>'
 
         res += '<p>The colors mainly correspond to those in vtkColors.txt.\n</p>\n'
 
         res += '<p>The colors mainly correspond to those in vtkColors.txt.\n</p>\n'
 
         res += '<p>The web colors (above) take precedence over colors of the same name in vtkColors.txt.</p>\n'
 
         res += '<p>The web colors (above) take precedence over colors of the same name in vtkColors.txt.</p>\n'
 
         res += '<table style="font-size:90%" cellpadding="4">\n'
 
         res += '<table style="font-size:90%" cellpadding="4">\n'
        res += '<caption style="background:lightgrey">VTK Color Names</caption>\n'
 
 
         res += '<tr valign="top">\n'
 
         res += '<tr valign="top">\n'
 
         res += self.MakeVTKColorTables()
 
         res += self.MakeVTKColorTables()
 
         res += '</table>\n'
 
         res += '</table>\n'
         res += '<h2>Synonyms</h2>'
+
         res += '<h2><a id="Synonyms">Synonyms</h2>'
 
         res += '<table style="font-size:90%" cellpadding="4">\n'
 
         res += '<table style="font-size:90%" cellpadding="4">\n'
        res += '<caption style="background:lightgrey">Synonyms</caption>\n'
 
 
         res += '<tr valign="top">\n'
 
         res += '<tr valign="top">\n'
 
         res += self.MakeSynonymColorTable()
 
         res += self.MakeSynonymColorTable()
Line 375: Line 332:
 
         res += '</body>\n'
 
         res += '</body>\n'
 
         return res
 
         return res
 +
 +
def CheckVTKVersion(requiredMajorVersion):
 +
    '''
 +
    Check the VTK version.
 +
    :param: requiredMajorVersion e.g. 6
 +
    '''
 +
    version = vtk.vtkVersion()
 +
    if version.GetVTKMajorVersion() > requiredMajorVersion:
 +
        raise
 +
    else:
 +
        return
  
 
if __name__ == "__main__":
 
if __name__ == "__main__":
    cp = MakeColorPatches()
+
    try:
    res = cp.MakeCombinedColorPage()
+
        CheckVTKVersion(6)
    f = open("VTKNamedColorPatches.html", "wb")
+
    except:
    f.write(res)
+
        print "You need VTK Version 6 or greater."
 
+
        print "The class vtkNamedColors is in VTK version 6 or greater."
 +
        exit(0)
 +
    cp = MakeColorPatches()
 +
    res = cp.MakeCombinedColorPage()
 +
    f = open("VTKNamedColorPatches.html", "wb")
 +
    f.write(res)
 
</source>
 
</source>

Revision as of 23:46, 27 June 2014

Description

This example shows how to produce a HTML page called VTKNamedColorPatches.html showing the available colors in vtkNamedColors.

It also shows how to select the text color based on luminance. In this case Digital CCIR601 is used which gives less weight to the red and blue components of a color.

NamedColorPatches.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

'''
=========================================================================

  Program:   Visualization Toolkit
  Module:    NamedColorPatches.py

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================

Produce a HTML page called VTKNamedColorPatches.html showing the available
 colors in vtkNamedColors.

It also shows how to select the text color based on luminance.
In this case Digital CCIR601 is used which gives less weight to the
 red and blue components of a color.

'''

import vtk

def RGBToHTMLColor(rgb):
    '''
    Convert an [R, G, B] list to #RRGGBB.
    :param: rgb - The elements of the array rgb are unsigned chars (0..255).
    :return: The html color.
    '''
    hexcolor = "#"+ ''.join(map(lambda x: '{:02x}'.format(x),rgb))
    return hexcolor

def HTMLColorToRGB(colorString):
    '''
    Convert #RRGGBB to a [R, G, B] list.
    :param: colorString a string in the form: #RRGGBB where RR, GG, BB are hexadecimal.
    The elements of the array rgb are unsigned chars (0..255).
    :return: The red, green and blue components as a list.
    '''
    colorString = colorString.strip()
    if colorString[0] == '#': colorString = colorString[1:]
    if len(colorString) != 6:
        raise ValueError, "Input #%s is not in #RRGGBB format" % colorString
    r, g, b = colorString[:2], colorString[2:4], colorString[4:]
    r, g, b = [int(n, 16) for n in (r, g, b)]
    return [r, g, b]

def RGBToLumaCCIR601(rgb):
    '''
    RGB -> Luma conversion
    Digital CCIR601 (gives less weight to the R and B components)
    :param: rgb - The elements of the array rgb are unsigned chars (0..255).
    :return: The luminance.
    '''
    Y = 0.299 * rgb[0] + 0.587 * rgb[1] + 0.114 * rgb[2]
    return Y

def FormatRGBForHTML(rgb):
    '''
    Format the rgb colors for display on a html table.
    :param: rgb - The elements of the array rgb are unsigned chars (0..255).
    :return: A formatted string for the html table.
    '''
    s = ','.join(map(lambda x: '{:3d}'.format(x),rgb))
    s = s.replace(' ','&#160;')
    s = s.replace(',','&#160;&#160;')
    return s

class MakeColorPatches(object):
    def __init__(self):
        self.cn = {
            'Red':['IndianRed', 'LightCoral', 'Salmon', 'DarkSalmon', 'LightSalmon', 'Red', 'Crimson', 'FireBrick', 'DarkRed'],
            'Pink':['Pink', 'LightPink', 'HotPink', 'DeepPink', 'MediumVioletRed', 'PaleVioletRed'],
            'Orange':['LightSalmon', 'Coral', 'Tomato', 'OrangeRed', 'DarkOrange', 'Orange'],
            'Yellow':['Gold', 'Yellow', 'LightYellow', 'LemonChiffon', 'LightGoldenrodYellow', 'PapayaWhip', 'Moccasin', 'PeachPuff', 'PaleGoldenrod', 'Khaki', 'DarkKhaki'],
            'Purple':['Lavender', 'Thistle', 'Plum', 'Violet', 'Orchid', 'Fuchsia', 'Magenta', 'MediumOrchid', 'MediumPurple', 'BlueViolet', 'DarkViolet', 'DarkOrchid', 'DarkMagenta', 'Purple', 'Indigo', 'DarkSlateBlue', 'SlateBlue', 'MediumSlateBlue'],
            'Green':['GreenYellow', 'Chartreuse', 'LawnGreen', 'Lime', 'LimeGreen', 'PaleGreen', 'LightGreen', 'MediumSpringGreen', 'SpringGreen', 'MediumSeaGreen', 'SeaGreen', 'ForestGreen', 'Green', 'DarkGreen', 'YellowGreen', 'OliveDrab', 'Olive', 'DarkOliveGreen', 'MediumAquamarine', 'DarkSeaGreen', 'LightSeaGreen', 'DarkCyan', 'Teal'],
            'Blue/Cyan':['Aqua', 'Cyan', 'LightCyan', 'PaleTurquoise', 'Aquamarine', 'Turquoise', 'MediumTurquoise', 'DarkTurquoise', 'CadetBlue', 'SteelBlue', 'LightSteelBlue', 'PowderBlue', 'LightBlue', 'SkyBlue', 'LightSkyBlue', 'DeepSkyBlue', 'DodgerBlue', 'CornflowerBlue', 'RoyalBlue', 'Blue', 'MediumBlue', 'DarkBlue', 'Navy', 'MidnightBlue'],
            'Brown':['Cornsilk', 'BlanchedAlmond', 'Bisque', 'NavajoWhite', 'Wheat', 'BurlyWood', 'Tan', 'RosyBrown', 'SandyBrown', 'Goldenrod', 'DarkGoldenrod', 'Peru', 'Chocolate', 'SaddleBrown', 'Sienna', 'Brown', 'Maroon'],
            'White':['White', 'Snow', 'Honeydew', 'MintCream', 'Azure', 'AliceBlue', 'GhostWhite', 'WhiteSmoke', 'Seashell', 'Beige', 'OldLace', 'FloralWhite', 'Ivory', 'AntiqueWhite', 'Linen', 'LavenderBlush', 'MistyRose'],
            'Gray':['Gainsboro', 'LightGrey', 'Silver', 'DarkGray', 'Gray', 'DimGray', 'LightSlateGray', 'SlateGray', 'DarkSlateGray', 'Black']
            }
        # Ordering of the tables and when to start and end a column of tables in the layout.
        self.cnOrder = ['Red', 'Pink', 'Orange', 'Yellow', 'Purple', 'Green', 'Blue/Cyan', 'Brown', 'White', 'Gray']
        self.cnStartTable = ['Red', 'Green', 'Brown']
        self.cnEndTable = ['Purple', 'Blue/Cyan', 'Gray']

        self.vtkcn = {
            'Whites':['antique_white', 'azure', 'bisque', 'blanched_almond', 'cornsilk', 'eggshell', 'floral_white', 'gainsboro', 'ghost_white', 'honeydew', 'ivory', 'lavender', 'lavender_blush', 'lemon_chiffon', 'linen', 'mint_cream', 'misty_rose', 'moccasin', 'navajo_white', 'old_lace', 'papaya_whip', 'peach_puff', 'seashell', 'snow', 'thistle', 'titanium_white', 'wheat', 'white', 'white_smoke', 'zinc_white'],
            'Greys':['cold_grey', 'dim_grey', 'grey', 'light_grey', 'slate_grey', 'slate_grey_dark', 'slate_grey_light', 'warm_grey'],
            'Blacks':['black', 'ivory_black', 'lamp_black'],
            'Reds':['alizarin_crimson', 'brick', 'cadmium_red_deep', 'coral', 'coral_light', 'deep_pink', 'english_red', 'firebrick', 'geranium_lake', 'hot_pink', 'indian_red', 'light_salmon', 'madder_lake_deep', 'maroon', 'pink', 'pink_light', 'raspberry', 'red', 'rose_madder', 'salmon', 'tomato', 'venetian_red'],
            'Browns':['beige', 'brown', 'brown_madder', 'brown_ochre', 'burlywood', 'burnt_sienna', 'burnt_umber', 'chocolate', 'deep_ochre', 'flesh', 'flesh_ochre', 'gold_ochre', 'greenish_umber', 'khaki', 'khaki_dark', 'light_beige', 'peru', 'rosy_brown', 'raw_sienna', 'raw_umber', 'sepia', 'sienna', 'saddle_brown', 'sandy_brown', 'tan', 'van_dyke_brown'],
            'Oranges':['cadmium_orange', 'cadmium_red_light', 'carrot', 'dark_orange', 'mars_orange', 'mars_yellow', 'orange', 'orange_red', 'yellow_ochre'],
            'Yellows':['aureoline_yellow', 'banana', 'cadmium_lemon', 'cadmium_yellow', 'cadmium_yellow_light', 'gold', 'goldenrod', 'goldenrod_dark', 'goldenrod_light', 'goldenrod_pale', 'light_goldenrod', 'melon', 'naples_yellow_deep', 'yellow', 'yellow_light'],
            'Greens':['chartreuse', 'chrome_oxide_green', 'cinnabar_green', 'cobalt_green', 'emerald_green', 'forest_green', 'green', 'green_dark', 'green_pale', 'green_yellow', 'lawn_green', 'lime_green', 'mint', 'olive', 'olive_drab', 'olive_green_dark', 'permanent_green', 'sap_green', 'sea_green', 'sea_green_dark', 'sea_green_medium', 'sea_green_light', 'spring_green', 'spring_green_medium', 'terre_verte', 'viridian_light', 'yellow_green'],
            'Cyans':['aquamarine', 'aquamarine_medium', 'cyan', 'cyan_white', 'turquoise', 'turquoise_dark', 'turquoise_medium', 'turquoise_pale'],
            'Blues':['alice_blue', 'blue', 'blue_light', 'blue_medium', 'cadet', 'cobalt', 'cornflower', 'cerulean', 'dodger_blue', 'indigo', 'manganese_blue', 'midnight_blue', 'navy', 'peacock', 'powder_blue', 'royal_blue', 'slate_blue', 'slate_blue_dark', 'slate_blue_light', 'slate_blue_medium', 'sky_blue', 'sky_blue_deep', 'sky_blue_light', 'steel_blue', 'steel_blue_light', 'turquoise_blue', 'ultramarine'],
            'Magentas':['blue_violet', 'cobalt_violet_deep', 'magenta', 'orchid', 'orchid_dark', 'orchid_medium', 'permanent_red_violet', 'plum', 'purple', 'purple_medium', 'ultramarine_violet', 'violet', 'violet_dark', 'violet_red', 'violet_red_medium', 'violet_red_pale']
            }
        # Ordering of the tables and when to start and end a column of tables in the layout.
        self.vtkcnOrder = ['Whites', 'Greys', 'Blacks', 'Reds', 'Oranges', 'Browns', 'Yellows', 'Greens', 'Cyans', 'Blues', 'Magentas']
        self.vtkcnStartTable = ['Whites', 'Browns', 'Cyans']
        self.vtkcnEndTable = ['Oranges', 'Greens', 'Magentas']
        # The vtkNamedColors class.
        self.nc = vtk.vtkNamedColors()

    def MakeHTMLHeader(self):
        s = '<!DOCTYPE html>\n'
        s += '<html lang="en" dir="ltr" class="client-nojs">\n'
        s += '<head>\n'
        s += '<title>vtkNamedColors</title>\n'
        s += '<meta charset="UTF-8" />\n'
        s += '</head>\n'
        return s

    def MakeHTMLIndex(self):
        s = '<h2>Index</h2>\n'
        s += '<ul>\n'
        s += '\t<li><a href="#WebColorNames">Web color Names</li>\n'
        s += '\t<li><a href="#VTKColorNames">VTK color Names</li>\n'
        s += '\t<li><a href="#Synonyms">Synonyms</li>\n'
        s += '</ul>\n'
        return s

    def MakeTableHeader(self):
        s = '<tr>\n'
        s += '<th style="background:lightgrey">HTML name</th>\n'
        s += '<th style="background:lightgrey">Decimal code<br />\n'
        s += '&#160;&#160;R&#160;&#160;&#160;&#160;&#160;&#160;G&#160;&#160;&#160;&#160;&#160;&#160;B</th>\n'
        s += '</tr>\n'
        return s

    def MakeSynonymTableHeader(self):
        s = '<tr>\n'
        s += '<th style="background:lightgrey">Synonyms</th>\n'
        s += '<th style="background:lightgrey">Decimal code<br />\n'
        s += '&#160;&#160;R&#160;&#160;&#160;&#160;&#160;&#160;G&#160;&#160;&#160;&#160;&#160;&#160;B</th>\n'
        s += '</tr>\n'
        return s

    def MakeTD(self, name):
        s = '<tr>\n'
        s += '<td colspan="2" style="background:whitesmoke;color:slategray;text-align:left"><big><b>' + name + '</b></big></td>\n'
        s += '</tr>\n'
        return s

    def MakeTR(self, name, rgb, textColor):
        s = '<tr>\n'
        s += '<td style="background:' + name + ';color:' + textColor + '">' + name + '</td>\n'
        s += '<td style="background:' + name + ';color:' + textColor + '"><tt>' + FormatRGBForHTML(rgb) + '</tt></td>\n'
        s += '</tr>\n'
        return s

    def MakeVTKTR(self, name, nameColor, rgb, textColor):
        s = '<tr>\n'
        s += '<td style="background:' + nameColor + ';color:' + textColor + '">' + name + '</td>\n'
        s += '<td style="background:' + nameColor + ';color:' + textColor + '"><tt>' + FormatRGBForHTML(rgb) + '</tt></td>\n'
        s += '</tr>\n'
        return s

    def FindLongestColorName(self):
        ''' Find the longest color name. '''
        maxLength = -1;
        for key, value in self.cn.iteritems():
            for val in value:
                if len(val) > maxLength:
                    maxLength = len(val)
        for key, value in self.vtkcn.iteritems():
            for val in value:
                if len(val) > maxLength:
                    maxLength = len(val)
        return maxLength

    def MakeWebColorTables(self):
        res = ''
        for key in self.cnOrder:
            if key in self.cnStartTable:
                res += '<td>\n'
                res += '<table>\n'
                res += self.MakeTableHeader()
            res += self.MakeTD(key + ' colors')
            values = self.cn[key]
            for name in values:
                rgb = self.nc.GetColor3ub(name)
                Y = RGBToLumaCCIR601(rgb)
                textColor = '#000000' # Black
                if Y < 255 / 2.0:
                    textColor = '#ffffff' # White
                res += self.MakeTR(name, rgb, textColor)
            if key in self.cnEndTable:
                res += '</table>\n'
                res += '</td>\n'
        return res

    def MakeVTKColorTables(self):
        res = ''
        for key in self.vtkcnOrder:
            if key in self.vtkcnStartTable:
                res += '<td>\n'
                res += '<table>\n'
                res += self.MakeTableHeader()
            res += self.MakeTD(key)
            values = self.vtkcn[key]
            for name in values:
                rgb = self.nc.GetColor3ub(name)
                Y = RGBToLumaCCIR601(rgb)
                textColor = '#000000' # Black
                if Y < 255 / 2.0:
                    textColor = '#ffffff' # White
                nameColor = RGBToHTMLColor(rgb)
                res += self.MakeVTKTR(name, nameColor, rgb, textColor)
            if key in self.vtkcnEndTable:
                res += '</table>\n'
                res += '</td>\n'
        return res

    def MakeSynonymColorTable(self):
        syn = self.nc.GetSynonyms()
        # Convert to a list where each element is a list of the
        #  color and its synonyms.
        syn = syn.split('\n\n')
        synonyms = []
        for ele in syn:
            synonyms.append(ele.split('\n'))
        cn = list()
        for key, value in self.cn.iteritems():
           cn = cn + value
        # Create a dictionary where the key is the lowercase name.
        d = dict()
        for n in cn:
            d.update({n.lower():n})
        res = '<td>\n'
        res += '<table>\n'
        res += self.MakeSynonymTableHeader()
        for colorNames in synonyms: #colors.GetSynonyms():
            for idx, name in enumerate(colorNames):
                if name in d:
                    colorNames[idx] = d[name]
            synonyms.sort()
            name = ", ".join(colorNames)
            rgb = self.nc.GetColor3ub(colorNames[0])
            Y = RGBToLumaCCIR601(rgb)
            textColor = '#000000' # Black
            if Y < 255 / 2.0:
                textColor = '#ffffff' # White
            nameColor = RGBToHTMLColor(rgb)
            res += self.MakeVTKTR(name, nameColor, rgb, textColor)
        res += '</table>\n'
        res += '</td>\n'
        return res

    def MakeWebColorPage(self):
        res = self.MakeHTMLHeader()
        res += '<body>\n'
        res += '<h1>Colors available in vtkNamedColors</h1>\n'
        res += '<table style="font-size:90%" cellpadding="4">\n'
        res += '<caption style="background:lightgrey">Web Color Names</caption>\n'
        res += '<tr valign="top">\n'
        res += self.MakeColorTables()
        res += '</table>\n'
        res += '</body>\n'
        return res

    def MakeVTKColorPage(self):
        res = self.MakeHTMLHeader()
        res += '<body>\n'
        res += '<h1>Colors available in vtkNamedColors</h1>\n'
        res += '<p>The web colors take precedence over colors of the same name in VTK Color Names.</p>\n'
        res += '<table style="font-size:90%" cellpadding="4">\n'
        res += '<caption style="background:lightgrey">VTK Color Names</caption>\n'
        res += '<tr valign="top">\n'
        res += self.MakeVTKColorTables()
        res += '</table>\n'
        res += '</body>\n'
        return res

    def MakeSynonymColorPage(self):
        res = self.MakeHTMLHeader()
        res += '<body>\n'
        res += '<h1>Synonyms in vtkNamedColors</h1>\n'
        res += '<table style="font-size:90%" cellpadding="4">\n'
        res += '<caption style="background:lightgrey"></caption>\n'
        res += '<tr valign="top">\n'
        res += self.MakeSynonymColorTable()
        res += '</table>\n'
        res += '</body>\n'
        return res

    def MakeCombinedColorPage(self):
        res = self.MakeHTMLHeader()
        res += '<body>\n'
        res += '<h1>Colors available in vtkNamedColors</h1>\n'
        res += '<p>The class vtkNamedColors provides color names and their values for the convenience of the user.</p>\n'
        res += '<p>The following tables show the available colors along with their red, green and blue values.</p>\n'
        res += self.MakeHTMLIndex()
        res += '<h2><a id="WebColorNames">Web color Names</h2>'
        res += 'These colors correspond to those in <a href="http://en.wikipedia.org/wiki/Web_colors" title="Web Colors">Web Colors</a>.\n'
        res += '<table style="font-size:90%" cellpadding="4">\n'
        res += '<tr valign="top">\n'
        res += self.MakeWebColorTables()
        res += '</table>\n'
        res += '<h2><a id="VTKColorNames">VTK color Names</h2>'
        res += '<p>The colors mainly correspond to those in vtkColors.txt.\n</p>\n'
        res += '<p>The web colors (above) take precedence over colors of the same name in vtkColors.txt.</p>\n'
        res += '<table style="font-size:90%" cellpadding="4">\n'
        res += '<tr valign="top">\n'
        res += self.MakeVTKColorTables()
        res += '</table>\n'
        res += '<h2><a id="Synonyms">Synonyms</h2>'
        res += '<table style="font-size:90%" cellpadding="4">\n'
        res += '<tr valign="top">\n'
        res += self.MakeSynonymColorTable()
        res += '</table>\n'
        res += '</body>\n'
        return res

def CheckVTKVersion(requiredMajorVersion):
    '''
    Check the VTK version.
    :param: requiredMajorVersion e.g. 6
    '''
    version = vtk.vtkVersion()
    if version.GetVTKMajorVersion() > requiredMajorVersion:
        raise
    else:
        return

if __name__ == "__main__":
    try:
        CheckVTKVersion(6)
    except:
        print "You need VTK Version 6 or greater."
        print "The class vtkNamedColors is in VTK version 6 or greater."
        exit(0)
    cp = MakeColorPatches()
    res = cp.MakeCombinedColorPage()
    f = open("VTKNamedColorPatches.html", "wb")
    f.write(res)