diff --git a/src/Cxx.md b/src/Cxx.md
index f6d42977f191ca7be231c7ff408d1ec4a09d902c..45372abf982c1bcfd3133283559e08b72e8880a7 100644
--- a/src/Cxx.md
+++ b/src/Cxx.md
@@ -635,6 +635,7 @@ This section includes vtkUnstructuredGrid.
 [Casting](/Cxx/PolyData/Casting) | Casting VTK objects.
 [CheckVTKVersion](/Cxx/Utilities/CheckVTKVersion) | Check VTK Version and provide alternatives for different VTK versions
 [ColorLookupTable](/Cxx/Utilities/ColorLookupTable) | Color Lookup Table.
+[ColorMapToLUT](/Cxx/Utilities/ColorMapToLUT) | Use vtkDiscretizableColorTransferFunction to generate a VTK colormap.
 [ColorTransferFunction](/Cxx/Utilities/ColorTransferFunction) | Color Transfer Function.
 [CommandSubclass](/Cxx/Utilities/CommandSubclass) | Instead of using a callback function, it is more powerful to subclass vtkCommand.
 [ConstrainedDelaunay2D](/Cxx/Filtering/ConstrainedDelaunay2D) | Perform a 2D Delaunay triangulation on a point set respecting a specified boundary.
diff --git a/src/Cxx/Utilities/ColorMapToLUT.cxx b/src/Cxx/Utilities/ColorMapToLUT.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..4b83db31fa3fe08addbf87d2b84575e22a0b357c
--- /dev/null
+++ b/src/Cxx/Utilities/ColorMapToLUT.cxx
@@ -0,0 +1,106 @@
+#include <vtkActor.h>
+#include <vtkConeSource.h>
+#include <vtkDiscretizableColorTransferFunction.h>
+#include <vtkElevationFilter.h>
+#include <vtkInteractorStyleTrackballCamera.h>
+#include <vtkNamedColors.h>
+#include <vtkNew.h>
+#include <vtkPolyDataMapper.h>
+#include <vtkProperty.h>
+#include <vtkRenderWindow.h>
+#include <vtkRenderWindowInteractor.h>
+#include <vtkRenderer.h>
+// #include <vtkSphereSource.h>
+
+#include <array>
+
+namespace {
+vtkNew<vtkDiscretizableColorTransferFunction> getCTF();
+
+}
+
+int main(int, char*[])
+{
+  std::array<unsigned char, 4> bkg{82, 87, 110, 255};
+  vtkNew<vtkNamedColors> colors;
+  colors->SetColor("ParaViewBkg", bkg.data());
+
+  vtkNew<vtkRenderer> ren;
+  ren->SetBackground(colors->GetColor3d("ParaViewBkg").GetData());
+  vtkNew<vtkRenderWindow> renWin;
+  renWin->SetSize(640, 480);
+  renWin->SetWindowName("ColorMapToLUT");
+  renWin->AddRenderer(ren);
+  vtkNew<vtkRenderWindowInteractor> iRen;
+  iRen->SetRenderWindow(renWin);
+
+  vtkNew<vtkInteractorStyleTrackballCamera> style;
+  iRen->SetInteractorStyle(style);
+
+  // vtkNew<vtkSphereSource> sphere;
+  // sphere->SetThetaResolution(64);
+  // sphere->SetPhiResolution(32);
+  // auto bounds = sphere->GetOutput()->GetBounds();
+
+  vtkNew<vtkConeSource> cone;
+  cone->SetResolution(6);
+  cone->SetDirection(0, 1, 0);
+  cone->SetHeight(1);
+  cone->Update();
+  auto bounds = cone->GetOutput()->GetBounds();
+
+  vtkNew<vtkElevationFilter> elevation_filter;
+  elevation_filter->SetLowPoint(0, bounds[2], 0);
+  elevation_filter->SetHighPoint(0, bounds[3], 0);
+  elevation_filter->SetInputConnection(cone->GetOutputPort());
+  // elevation_filter->SetInputConnection(sphere->GetOutputPort());
+
+  auto ctf = getCTF();
+
+  vtkNew<vtkPolyDataMapper> mapper;
+  mapper->SetInputConnection(elevation_filter->GetOutputPort());
+  mapper->SetLookupTable(ctf);
+  mapper->SetColorModeToMapScalars();
+  mapper->InterpolateScalarsBeforeMappingOn();
+
+  vtkNew<vtkActor> actor;
+  actor->SetMapper(mapper);
+
+  ren->AddActor(actor);
+
+  renWin->Render();
+  iRen->Start();
+
+  return EXIT_SUCCESS;
+}
+
+namespace {
+
+vtkNew<vtkDiscretizableColorTransferFunction> getCTF()
+{
+  // name: Fast, creator: Francesca Samsel, file name: Fast.xml
+  vtkNew<vtkDiscretizableColorTransferFunction> ctf;
+
+  ctf->SetColorSpaceToLab();
+  ctf->SetScaleToLinear();
+
+  ctf->SetNanColor(0, 0, 0);
+
+  ctf->AddRGBPoint(0, 0.08800000000000002, 0.18810000000000007, 0.55);
+  ctf->AddRGBPoint(0.16144, 0.21989453864645603, 0.5170512023315895,
+                   0.7093372214401806);
+  ctf->AddRGBPoint(0.351671, 0.5048913252297864, 0.8647869538833338,
+                   0.870502284878942);
+  ctf->AddRGBPoint(0.501285, 1, 1, 0.83);
+  ctf->AddRGBPoint(0.620051, 0.9418960444346476, 0.891455547964053,
+                   0.5446035798119958);
+  ctf->AddRGBPoint(0.835408342528245, 0.75, 0.44475, 0.255);
+  ctf->AddRGBPoint(1, 0.56, 0.055999999999999994, 0.055999999999999994);
+
+  ctf->SetNumberOfValues(7);
+  ctf->DiscretizeOff();
+
+  return ctf;
+}
+
+} // namespace
diff --git a/src/Cxx/Utilities/ColorMapToLUT.md b/src/Cxx/Utilities/ColorMapToLUT.md
new file mode 100644
index 0000000000000000000000000000000000000000..f5d0b1d66b9c8dff677ad160d1044c83bd506404
--- /dev/null
+++ b/src/Cxx/Utilities/ColorMapToLUT.md
@@ -0,0 +1,12 @@
+### Description
+
+Demonstrate a cone using the vtkDiscretizableColorTransferFunction to generate the colormap.
+
+These two Python programs can be used to generate the function `def get_ctf(): ...` or `vtkNew<vtkDiscretizableColorTransferFunction> getCTF() ...` for either an XML description of a colormap or a JSON one.
+
+- [ColorMapToLUT_XML](../../../Python/Utilities/ColorMapToLUT_XML/)
+- [ColorMapToLUT_JSON](../../../Python/Utilities/ColorMapToLUT_JSON/)
+
+Feel free to use either of these programs to generate different colormaps until you find one you like.
+
+A good initial source for color maps is: [SciVisColor](https://sciviscolor.org/) -- this will provide you with plenty of XML examples.
diff --git a/src/Python.md b/src/Python.md
index 87055c636db4df14c94cfd3dc89062141d21404d..6fcae4fa2c3163019b5da604d5ee6ab602a42809 100644
--- a/src/Python.md
+++ b/src/Python.md
@@ -365,6 +365,9 @@ This section includes vtkUnstructuredGrid.
 | Example Name | Description | Image |
 | -------------- | ------------- | ------- |
 [CheckVTKVersion](/Python/Utilities/CheckVTKVersion) | Check the VTK version and provide alternatives for different VTK versions.
+[ColorMapToLUT_JSON](/Python/Utilities/ColorMapToLUT_JSON) | Take an JSON description of a colormap and convert it to a VTK colormap.
+[ColorMapToLUT_XML](/Python/Utilities/ColorMapToLUT_XML) | Take an XML description of a colormap and convert it to a VTK colormap.
+[ColorMapToLUT](/Python/Utilities/ColorMapToLUT) | Use vtkDiscretizableColorTransferFunction to generate a VTK colormap.
 [ConstrainedDelaunay2D](/Python/Filtering/ConstrainedDelaunay2D) | Perform a 2D Delaunay triangulation on a point set respecting a specified boundary.
 [Delaunay2D](/Python/Filtering/Delaunay2D) |
 [LUTUtilities](/Python/Utilities/LUTUtilities) | A utility class for vtkLookupTable allowing you to output the table contents or to compare tables.
diff --git a/src/Python/Utilities/ColorMapToLUT.md b/src/Python/Utilities/ColorMapToLUT.md
new file mode 100644
index 0000000000000000000000000000000000000000..9479f33cdcc33bfbfbef2b2040dddaab556912d4
--- /dev/null
+++ b/src/Python/Utilities/ColorMapToLUT.md
@@ -0,0 +1,12 @@
+### Description
+
+Demonstrate a cone using the vtkDiscretizableColorTransferFunction to generate the colormap.
+
+These two Python programs can be used to generate the function `def get_ctf(): ...` or `vtkNew<vtkDiscretizableColorTransferFunction> getCTF() ...` for either an XML description of a colormap or a JSON one.
+
+- [ColorMapToLUT_XML](../ColorMapToLUT_XML/)
+- [ColorMapToLUT_JSON](../ColorMapToLUT_JSON/)
+
+Feel free to use either of these programs to generate different colormaps until you find one you like.
+
+A good initial source for color maps is: [SciVisColor](https://sciviscolor.org/) -- this will provide you with plenty of XML examples.
diff --git a/src/Python/Utilities/ColorMapToLUT.py b/src/Python/Utilities/ColorMapToLUT.py
new file mode 100755
index 0000000000000000000000000000000000000000..ede92404c81bf4ba53cbb1fad5b5852fa876f8bc
--- /dev/null
+++ b/src/Python/Utilities/ColorMapToLUT.py
@@ -0,0 +1,93 @@
+#!/usr/bin/env python3
+
+# noinspection PyUnresolvedReferences
+import vtkmodules.vtkRenderingOpenGL2
+from vtkmodules.vtkCommonColor import vtkNamedColors
+from vtkmodules.vtkFiltersCore import vtkElevationFilter
+from vtkmodules.vtkFiltersSources import vtkConeSource, vtkSphereSource
+from vtkmodules.vtkInteractionStyle import vtkInteractorStyleTrackballCamera
+from vtkmodules.vtkRenderingCore import (
+    vtkActor,
+    vtkDiscretizableColorTransferFunction,
+    vtkPolyDataMapper,
+    vtkRenderWindow,
+    vtkRenderWindowInteractor,
+    vtkRenderer
+)
+
+
+def main():
+    colors = vtkNamedColors()
+    colors.SetColor('ParaViewBkg', 82, 87, 110, 255)
+
+    ren = vtkRenderer()
+    ren.SetBackground(colors.GetColor3d('ParaViewBkg'))
+    ren_win = vtkRenderWindow()
+    ren_win.SetSize(640, 480)
+    ren_win.SetWindowName('ColorMapToLUT')
+    ren_win.AddRenderer(ren)
+    iren = vtkRenderWindowInteractor()
+    iren.SetRenderWindow(ren_win)
+
+    style = vtkInteractorStyleTrackballCamera()
+    iren.SetInteractorStyle(style)
+
+    sphere = vtkSphereSource()
+    sphere.SetThetaResolution(64)
+    sphere.SetPhiResolution(32)
+
+    cone = vtkConeSource()
+    cone.SetResolution(6)
+    cone.SetDirection(0, 1, 0)
+    cone.SetHeight(1)
+    cone.Update()
+    bounds = cone.GetOutput().GetBounds()
+
+    elevation_filter = vtkElevationFilter()
+    elevation_filter.SetLowPoint(0, bounds[2], 0)
+    elevation_filter.SetHighPoint(0, bounds[3], 0)
+    elevation_filter.SetInputConnection(cone.GetOutputPort())
+    # elevation_filter.SetInputConnection(sphere.GetOutputPort())
+
+    ctf = get_ctf()
+
+    mapper = vtkPolyDataMapper()
+    mapper.SetInputConnection(elevation_filter.GetOutputPort())
+    mapper.SetLookupTable(ctf)
+    mapper.SetColorModeToMapScalars()
+    mapper.InterpolateScalarsBeforeMappingOn()
+
+    actor = vtkActor()
+    actor.SetMapper(mapper)
+
+    ren.AddActor(actor)
+
+    ren_win.Render()
+    iren.Start()
+
+
+def get_ctf():
+    # name: Fast, creator: Francesca Samsel, file name: Fast.xml
+    ctf = vtkDiscretizableColorTransferFunction()
+
+    ctf.SetColorSpaceToLab()
+    ctf.SetScaleToLinear()
+
+    ctf.SetNanColor(0, 0, 0)
+
+    ctf.AddRGBPoint(0, 0.08800000000000002, 0.18810000000000007, 0.55)
+    ctf.AddRGBPoint(0.16144, 0.21989453864645603, 0.5170512023315895, 0.7093372214401806)
+    ctf.AddRGBPoint(0.351671, 0.5048913252297864, 0.8647869538833338, 0.870502284878942)
+    ctf.AddRGBPoint(0.501285, 1, 1, 0.83)
+    ctf.AddRGBPoint(0.620051, 0.9418960444346476, 0.891455547964053, 0.5446035798119958)
+    ctf.AddRGBPoint(0.835408342528245, 0.75, 0.44475, 0.255)
+    ctf.AddRGBPoint(1, 0.56, 0.055999999999999994, 0.055999999999999994)
+
+    ctf.SetNumberOfValues(7)
+    ctf.DiscretizeOn()
+
+    return ctf
+
+
+if __name__ == '__main__':
+    main()
diff --git a/src/Python/Utilities/ColorMapToLUT_JSON.md b/src/Python/Utilities/ColorMapToLUT_JSON.md
new file mode 100644
index 0000000000000000000000000000000000000000..08a0cb41155964f4b9af33717daba659a1a19ff2
--- /dev/null
+++ b/src/Python/Utilities/ColorMapToLUT_JSON.md
@@ -0,0 +1,16 @@
+### Description
+
+Generate a VTK colormap from an ParaView JSON description of a colormap.
+
+A cone is rendered to demonstrate the resultant colormap. C++ and Python functions can also be generated which implement the colormap. These can be copied into [ColorMapToLUT.cxx]() or [ColorMapToLUT.py]() or into your own code.
+
+This program was inspired by this discussion: [Replacement default color map and background palette](https://discourse.paraview.org/t/replacement-default-color-map-and-background-palette/12712), the **Fast** colormap from this discussion is used as test data here.
+
+A good initial source for color maps is: [SciVisColor](https://sciviscolor.org/) -- this will provide you with plenty of XML examples.
+
+Further information:
+
+- [VTK Examples - Some ColorMap to LookupTable tools]()
+- [How to export ParaView colormap into a format that could be read by matplotlib](https://discourse.paraview.org/t/how-to-export-paraview-colormap-into-a-format-that-could-be-read-by-matplotlib/2436)
+- [How to export ParaView colormap into a format that could be read by matplotlib?](https://discourse.paraview.org/t/how-to-export-paraview-colormap-into-a-format-that-could-be-read-by-matplotlib/2394)
+- [Color map advice and resources](https://discourse.paraview.org/t/color-map-advice-and-resources/6452/4)
diff --git a/src/Python/Utilities/ColorMapToLUT_JSON.py b/src/Python/Utilities/ColorMapToLUT_JSON.py
new file mode 100755
index 0000000000000000000000000000000000000000..2bc548e877b4e77516fe4d31178377c1436c5aca
--- /dev/null
+++ b/src/Python/Utilities/ColorMapToLUT_JSON.py
@@ -0,0 +1,435 @@
+#!/usr/bin/env python3
+
+import json
+import sys
+from pathlib import Path
+
+# noinspection PyUnresolvedReferences
+import vtkmodules.vtkRenderingOpenGL2
+from vtkmodules.vtkCommonColor import vtkNamedColors
+from vtkmodules.vtkFiltersCore import vtkElevationFilter
+from vtkmodules.vtkFiltersSources import vtkConeSource, vtkSphereSource
+from vtkmodules.vtkInteractionStyle import vtkInteractorStyleTrackballCamera
+from vtkmodules.vtkRenderingCore import (
+    vtkActor,
+    vtkPolyDataMapper,
+    vtkRenderWindow,
+    vtkRenderWindowInteractor,
+    vtkRenderer
+)
+from vtkmodules.vtkRenderingCore import (
+    vtkDiscretizableColorTransferFunction,
+)
+
+
+def get_program_parameters(argv):
+    import argparse
+    description = 'Take a JSON description of a colormap and convert it to a VTK colormap.'
+    epilogue = '''
+    A color transfer function in C++ or Python can be optionally generated.
+    '''
+    parser = argparse.ArgumentParser(description=description, epilog=epilogue,
+                                     formatter_class=argparse.RawDescriptionHelpFormatter)
+
+    parser.add_argument('file_name', help='The path to the JSONL file e.g Fast.xml.')
+    parser.add_argument('-d', action='store_true', dest='discretize', help='Discretize the colormap.')
+    parser.add_argument('-n', dest='table_size', default=None, type=int,
+                        help='Specify the size of the colormap.')
+    parser.add_argument('-g', dest='generate_function', default=None,
+                        help='Generate code for the color transfer function,'
+                             ' specify the desired language one of: Cxx, Python.')
+
+    args = parser.parse_args()
+    return args.file_name, args.discretize, args.table_size, args.generate_function
+
+
+def main(file_name, discretize, table_size, generate_function):
+    if file_name:
+        fn_path = Path(file_name)
+        if not fn_path.suffix:
+            fn_path = fn_path.with_suffix(".json")
+        if not fn_path.is_file():
+            print('Unable to find: ', fn_path)
+            return
+    else:
+        print('Please enter a path to the JSON file.')
+        return
+    parameters = parse_json(fn_path)
+    # Do some checks.
+    if len(parameters['data_values']) != len(parameters['color_values']):
+        sys.exit('The data values length must be the same as colors.')
+    if len(parameters['opacity_values']) > 0:
+        if len(parameters['opacity_values']) != len(parameters['color_values']):
+            sys.exit('The opacity values length must be the same as colors.')
+
+    if generate_function is not None:
+        generate_function = generate_function.lower()
+        available_languages = {k.lower(): k for k in ['Cxx', 'Python']}
+        available_languages.update({'cpp': 'Cxx', 'c++': 'Cxx'})
+        if generate_function not in available_languages:
+            print(f'The language: {generate_function} is not available.')
+            tmp = ', '.join(sorted([lang for lang in set(available_languages.values())]))
+            print(f'Choose one of these: {tmp}.')
+            return
+        else:
+            language = available_languages[generate_function]
+    else:
+        language = None
+
+    ctf = make_ctf(parameters, discretize, table_size)
+    if language is not None and language in ['Cxx', 'Python']:
+        if language == 'Python':
+            generate_ctf_python(parameters, discretize, table_size)
+        else:
+            generate_ctf_cpp(parameters, discretize, table_size)
+
+    colors = vtkNamedColors()
+    colors.SetColor('ParaViewBkg', 82, 87, 110, 255)
+
+    sphere = vtkSphereSource()
+    sphere.SetThetaResolution(64)
+    sphere.SetPhiResolution(32)
+
+    cone = vtkConeSource()
+    cone.SetResolution(6)
+    cone.SetDirection(0, 1, 0)
+    cone.SetHeight(1)
+    cone.Update()
+    bounds = cone.GetOutput().GetBounds()
+
+    elevation_filter = vtkElevationFilter()
+    elevation_filter.SetLowPoint(0, bounds[2], 0)
+    elevation_filter.SetHighPoint(0, bounds[3], 0)
+    elevation_filter.SetInputConnection(cone.GetOutputPort())
+    # elevation_filter.SetInputConnection(sphere.GetOutputPort())
+
+    mapper = vtkPolyDataMapper()
+    mapper.SetInputConnection(elevation_filter.GetOutputPort())
+    mapper.SetLookupTable(ctf)
+    mapper.SetColorModeToMapScalars()
+    mapper.InterpolateScalarsBeforeMappingOn()
+
+    actor = vtkActor()
+    actor.SetMapper(mapper)
+    # actor.GetProperty().SetDiffuseColor(colors.GetColor3d('bisque'))
+
+    # Visualize
+    ren = vtkRenderer()
+    ren_win = vtkRenderWindow()
+    ren_win.AddRenderer(ren)
+    iren = vtkRenderWindowInteractor()
+    iren.SetRenderWindow(ren_win)
+
+    style = vtkInteractorStyleTrackballCamera()
+    iren.SetInteractorStyle(style)
+
+    ren.AddActor(actor)
+    ren.SetBackground(colors.GetColor3d('ParaViewBkg'))
+
+    ren_win.SetSize(640, 480)
+    ren_win.SetWindowName('ColorMapToLUT_JSON')
+
+    ren_win.Render()
+    iren.Start()
+
+
+def parse_json(fn_path):
+    """
+    Parse the exported ParaView JSON file of a colormap.
+    :param fn_path: The path to the JSON file.
+    :return: The parameters for the color map.
+    """
+    with open(fn_path) as data_file:
+        json_data = json.load(data_file)
+    data_values = list()
+    color_values = list()
+    opacity_values = list()
+    color_map_details = dict()
+    nan = None
+    above = None
+    below = None
+    for k, v in json_data[0].items():
+        if 'Points' in k:
+            n = 4
+            data_color = [v[i * n:(i + 1) * n] for i in range((len(v) + n - 1) // n)]
+            for dc in data_color:
+                if len(dc) == 4:
+                    data_values.append(dc[0])
+                    color_values.append(tuple(dc[1:]))
+        if k == 'ColorSpace':
+            color_map_details['space'] = v
+        if k == 'Creator':
+            color_map_details['creator'] = v
+        if k == 'Name':
+            color_map_details['name'] = v
+        if k == 'NanColor':
+            nan = tuple(v[0:3])
+    return {'path': fn_path.name, 'color_map_details': color_map_details, 'data_values': data_values,
+            'color_values': color_values, 'opacity_values': opacity_values, 'NaN': nan, 'Above': above, 'Below': below}
+
+
+def make_ctf(parameters, discretize, table_size=None):
+    """
+    Generate the discretizable color transfer function
+    :param parameters: The parameters.
+    :param discretize: True if the values are to be mapped after discretization.
+    :param table_size: The table size.
+    :return: The discretizable color transfer function.
+    """
+
+    ctf = vtkDiscretizableColorTransferFunction()
+
+    interp_space = parameters['color_map_details'].get('interpolationspace', None)
+    if interp_space:
+        interp_space = interp_space.lower()
+        if interp_space == 'hsv':
+            ctf.SetColorSpaceToHSV()
+        elif interp_space == 'lab':
+            ctf.SetColorSpaceToLab()
+        elif interp_space == 'ciede2000':
+            ctf.SetColorSpaceToLabCIEDE2000()
+        elif interp_space == 'diverging':
+            ctf.SetColorSpaceToDiverging()
+        elif interp_space == 'step':
+            ctf.SetColorSpaceToStep()
+        else:
+            ctf.SetColorSpaceToRGB()
+    else:
+        ctf.SetColorSpaceToRGB()
+
+    scale = parameters['color_map_details'].get('interpolationtype', None)
+    if scale:
+        scale = scale.lower()
+        if scale == 'log10':
+            ctf.SetScaleToLog10()
+        else:
+            ctf.SetScaleToLinear()
+    else:
+        ctf.SetScaleToLinear()
+
+    if parameters['NaN'] is not None:
+        ctf.SetNanColor(*parameters['NaN'])
+
+    if parameters['Above'] is not None:
+        ctf.SetAboveRangeColor(*parameters['Above'])
+        ctf.UseAboveRangeColorOn()
+
+    if parameters['Below'] is not None:
+        ctf.SetBelowRangeColor(*parameters['Below'])
+        ctf.UseBelowRangeColorOn()
+
+    space = parameters['color_map_details'].get('space', None)
+    if space:
+        space = space.lower()
+        for i in range(0, len(parameters['data_values'])):
+            idx = parameters['data_values'][i]
+            color = parameters['color_values'][i]
+            if space == 'hsv':
+                ctf.AddHSVPoint(idx, *color)
+            else:
+                ctf.AddRGBPoint(idx, *color)
+
+    if table_size is not None:
+        ctf.SetNumberOfValues(table_size)
+    else:
+        ctf.SetNumberOfValues(len(parameters["data_values"]))
+
+    if discretize:
+        ctf.DiscretizeOn()
+    else:
+        ctf.DiscretizeOff()
+
+    return ctf
+
+
+def generate_ctf_python(parameters, discretize, table_size=None):
+    """
+    Generate a function do the ctf.
+
+    :param parameters: The parameters.
+    :param discretize: True if the values are to be mapped after discretization.
+    :param table_size: The table size.
+    :return: The discretizable color transfer function.
+    """
+    indent = ' ' * 4
+
+    comment = f'{indent}#'
+    if 'name' in parameters['color_map_details']:
+        comment += f' name: {parameters["color_map_details"]["name"]},'
+    if 'creator' in parameters['color_map_details']:
+        comment += f' creator: {parameters["color_map_details"]["creator"]},'
+    comment += f' file name: {parameters["path"]}'
+
+    s = ['', f'def get_ctf():', comment, f'{indent}ctf = vtkDiscretizableColorTransferFunction()', '']
+
+    interp_space = parameters['color_map_details'].get('interpolationspace', None)
+    if interp_space:
+        interp_space = interp_space.lower()
+        if interp_space == 'hsv':
+            s.append(f'{indent}ctf.SetColorSpaceToHSV()')
+        elif interp_space == 'lab':
+            s.append(f'{indent}ctf.SetColorSpaceToLab()')
+        elif interp_space == 'ciede2000':
+            s.append(f'{indent}ctf.SetColorSpaceToLabCIEDE2000()')
+        elif interp_space == 'diverging':
+            s.append(f'{indent}ctf.SetColorSpaceToDiverging()')
+        elif interp_space == 'step':
+            s.append(f'{indent}ctf.SetColorSpaceToStep()')
+        else:
+            s.append(f'{indent}ctf.SetColorSpaceToRGB()')
+    else:
+        s.append(f'{indent}ctf.SetColorSpaceToRGB()')
+
+    scale = parameters['color_map_details'].get('interpolationtype', None)
+    if scale:
+        scale = scale.lower()
+        if scale == 'log10':
+            s.append(f'{indent}ctf.SetScaleToLog10()')
+        else:
+            s.append(f'{indent}ctf.SetScaleToLinear()')
+    else:
+        s.append(f'{indent}ctf.SetScaleToLinear()')
+    s.append('')
+
+    if parameters['NaN'] is not None:
+        color = ', '.join(list(map(str, parameters['NaN'])))
+        s.append(f'{indent}ctf.SetNanColor({color})')
+
+    if parameters['Above'] is not None:
+        color = ', '.join(list(map(str, parameters['Above'])))
+        s.append(f'{indent}ctf.SetAboveRangeColor({color})')
+        s.append(f'{indent}ctf.UseAboveRangeColorOn()')
+
+    if parameters['Below'] is not None:
+        color = ', '.join(list(map(str, parameters['Below'])))
+        s.append(f'{indent}ctf.SetBelowRangeColor({color})')
+        s.append(f'{indent}ctf.UseBelowRangeColorOn()')
+    s.append('')
+
+    space = parameters['color_map_details'].get('space', None)
+    if space:
+        space = space.lower()
+        for i in range(0, len(parameters['data_values'])):
+            color = ', '.join(list(map(str, parameters['color_values'][i])))
+            idx = parameters['data_values'][i]
+            if space == 'hsv':
+                s.append(f'{indent}ctf.AddHSVPoint({idx}, {color})')
+            else:
+                s.append(f'{indent}ctf.AddRGBPoint({idx}, {color})')
+        s.append('')
+
+    if table_size is not None:
+        s.append(f'{indent}ctf.SetNumberOfValues({table_size})')
+    else:
+        s.append(f'{indent}ctf.SetNumberOfValues({len(parameters["data_values"])})')
+
+    if discretize:
+        s.append(f'{indent}ctf.DiscretizeOn()')
+    else:
+        s.append(f'{indent}ctf.DiscretizeOff()')
+    s.append('')
+
+    s.append(f'{indent}return ctf')
+    s.append('')
+
+    print('\n'.join(s))
+
+
+def generate_ctf_cpp(parameters, discretize, table_size=None):
+    """
+    Generate a function do the ctf.
+
+    :param parameters: The parameters.
+    :param discretize: True if the values are to be mapped after discretization.
+    :param table_size: The table size.
+    :return: The discretizable color transfer function.
+    """
+    indent = ' ' * 2
+
+    comment = f'{indent}//'
+    if 'name' in parameters['color_map_details']:
+        comment += f' name: {parameters["color_map_details"]["name"]},'
+    if 'creator' in parameters['color_map_details']:
+        comment += f' creator: {parameters["color_map_details"]["creator"]},'
+    comment += f' file name: {parameters["path"]}'
+
+    s = ['', f'vtkNew<vtkDiscretizableColorTransferFunction> getCTF()', '{', comment,
+         f'{indent}vtkNew<vtkDiscretizableColorTransferFunction> ctf;', '']
+
+    interp_space = parameters['color_map_details'].get('interpolationspace', None)
+    if interp_space:
+        interp_space = interp_space.lower()
+        if interp_space == 'hsv':
+            s.append(f'{indent}ctf->SetColorSpaceToHSV();')
+        elif interp_space == 'lab':
+            s.append(f'{indent}ctf->SetColorSpaceToLab();')
+        elif interp_space == 'ciede2000':
+            s.append(f'{indent}ctf->SetColorSpaceToLabCIEDE2000();')
+        elif interp_space == 'diverging':
+            s.append(f'{indent}ctf->SetColorSpaceToDiverging();')
+        elif interp_space == 'step':
+            s.append(f'{indent}ctf->SetColorSpaceToStep();')
+        else:
+            s.append(f'{indent}ctf->SetColorSpaceToRGB();')
+    else:
+        s.append(f'{indent}ctf->SetColorSpaceToRGB();')
+
+    scale = parameters['color_map_details'].get('interpolationtype', None)
+    if scale:
+        scale = scale.lower()
+        if scale == 'log10':
+            s.append(f'{indent}ctf->SetScaleToLog10();')
+        else:
+            s.append(f'{indent}ctf->SetScaleToLinear();')
+    else:
+        s.append(f'{indent}ctf->SetScaleToLinear();')
+    s.append('')
+
+    if parameters['NaN'] is not None:
+        color = ', '.join(list(map(str, parameters['NaN'])))
+        s.append(f'{indent}ctf->SetNanColor({color});')
+
+    if parameters['Above'] is not None:
+        color = ', '.join(list(map(str, parameters['Above'])))
+        s.append(f'{indent}ctf->SetAboveRangeColor({color});')
+        s.append(f'{indent}ctf->UseAboveRangeColorOn();')
+
+    if parameters['Below'] is not None:
+        color = ', '.join(list(map(str, parameters['Below'])))
+        s.append(f'{indent}ctf->SetBelowRangeColor({color});')
+        s.append(f'{indent}ctf->UseBelowRangeColorOn();')
+    s.append('')
+
+    space = parameters['color_map_details'].get('space', None)
+    if space:
+        space = space.lower()
+        for i in range(0, len(parameters['data_values'])):
+            color = ', '.join(list(map(str, parameters['color_values'][i])))
+            idx = parameters['data_values'][i]
+            if space == 'hsv':
+                s.append(f'{indent}ctf->AddHSVPoint({idx}, {color});')
+            else:
+                s.append(f'{indent}ctf->AddRGBPoint({idx}, {color});')
+        s.append('')
+
+    if table_size is not None:
+        s.append(f'{indent}ctf->SetNumberOfValues({table_size});')
+    else:
+        s.append(f'{indent}ctf->SetNumberOfValues({len(parameters["data_values"])});')
+
+    if discretize:
+        s.append(f'{indent}ctf->DiscretizeOn();')
+    else:
+        s.append(f'{indent}ctf->DiscretizeOff();')
+    s.append('')
+
+    s.append(f'{indent}return ctf;')
+    s.append('}')
+    s.append('')
+
+    print('\n'.join(s))
+
+
+if __name__ == '__main__':
+    file, discretise, size, generate = get_program_parameters(sys.argv)
+    main(file, discretise, size, generate)
diff --git a/src/Python/Utilities/ColorMapToLUT_XML.md b/src/Python/Utilities/ColorMapToLUT_XML.md
new file mode 100644
index 0000000000000000000000000000000000000000..fae07b138a004f0338ebb9160c2c340468aec5af
--- /dev/null
+++ b/src/Python/Utilities/ColorMapToLUT_XML.md
@@ -0,0 +1,21 @@
+### Description
+
+Generate a VTK colormap from an XML description of a colormap.
+
+A cone is rendered to demonstrate the resultant colormap. C++ and Python functions can also be generated which implement the colormap. These can be copied into [ColorMapToLUT.cxx]() or [ColorMapToLUT.py]() or into your own code.
+
+This program was inspired by this discussion: [Replacement default color map and background palette](https://discourse.paraview.org/t/replacement-default-color-map-and-background-palette/12712), and,  the **Fast** colormap from this discussion is used as test data here.
+
+A good initial source for color maps is: [SciVisColor](https://sciviscolor.org/) -- this will provide you with plenty of XML examples.
+
+**Note:** 
+
+- The XML parser is [lxml](https://lxml.de/)
+- Currently the parsing only works for colormaps with no Section key.
+
+Further information:
+
+- [VTK Examples - Some ColorMap to LookupTable tools]()
+- [How to export ParaView colormap into a format that could be read by matplotlib](https://discourse.paraview.org/t/how-to-export-paraview-colormap-into-a-format-that-could-be-read-by-matplotlib/2436)
+- [How to export ParaView colormap into a format that could be read by matplotlib?](https://discourse.paraview.org/t/how-to-export-paraview-colormap-into-a-format-that-could-be-read-by-matplotlib/2394)
+- [Color map advice and resources](https://discourse.paraview.org/t/color-map-advice-and-resources/6452/4)
diff --git a/src/Python/Utilities/ColorMapToLUT_XML.py b/src/Python/Utilities/ColorMapToLUT_XML.py
new file mode 100755
index 0000000000000000000000000000000000000000..f0bf47fe83f1b0e08b04736732dce91f0b45b242
--- /dev/null
+++ b/src/Python/Utilities/ColorMapToLUT_XML.py
@@ -0,0 +1,443 @@
+#!/usr/bin/env python3
+
+import sys
+from pathlib import Path
+
+# noinspection PyUnresolvedReferences
+import vtkmodules.vtkRenderingOpenGL2
+from lxml import etree
+from vtkmodules.vtkCommonColor import vtkNamedColors
+from vtkmodules.vtkFiltersCore import vtkElevationFilter
+from vtkmodules.vtkFiltersSources import vtkConeSource, vtkSphereSource
+from vtkmodules.vtkInteractionStyle import vtkInteractorStyleTrackballCamera
+from vtkmodules.vtkRenderingCore import (
+    vtkActor,
+    vtkPolyDataMapper,
+    vtkRenderWindow,
+    vtkRenderWindowInteractor,
+    vtkRenderer
+)
+from vtkmodules.vtkRenderingCore import (
+    vtkDiscretizableColorTransferFunction,
+)
+
+
+def get_program_parameters(argv):
+    import argparse
+    description = 'Take an XML description of a colormap and convert it to a VTK colormap.'
+    epilogue = '''
+    A color transfer function in C++ or Python can be optionally generated.
+    '''
+    parser = argparse.ArgumentParser(description=description, epilog=epilogue,
+                                     formatter_class=argparse.RawDescriptionHelpFormatter)
+
+    parser.add_argument('file_name', help='The path to the XML file e.g Fast.xml.')
+    parser.add_argument('-d', action='store_true', dest='discretize', help='Discretize the colormap.')
+    parser.add_argument('-n', dest='table_size', default=None, type=int,
+                        help='Specify the size of the colormap.')
+    parser.add_argument('-g', dest='generate_function', default=None,
+                        help='Generate code for the color transfer function,'
+                             ' specify the desired language one of: Cxx, Python.')
+
+    args = parser.parse_args()
+    return args.file_name, args.discretize, args.table_size, args.generate_function
+
+
+def main(file_name, discretize, table_size, generate_function):
+    if file_name:
+        fn_path = Path(file_name)
+        if not fn_path.suffix:
+            fn_path = fn_path.with_suffix(".xml")
+        if not fn_path.is_file():
+            print('Unable to find: ', fn_path)
+            return
+    else:
+        print('Please enter a path to the XML file.')
+        return
+    parameters = parse_xml(fn_path)
+    # Do some checks.
+    if len(parameters['data_values']) != len(parameters['color_values']):
+        sys.exit('The data values length must be the same as colors.')
+    if parameters['opacity_values'] is not None:
+        if len(parameters['opacity_values']) != len(parameters['color_values']):
+            sys.exit('The opacity values length must be the same as colors.')
+
+    if generate_function is not None:
+        generate_function = generate_function.lower()
+        available_languages = {k.lower(): k for k in ['Cxx', 'Python']}
+        available_languages.update({'cpp': 'Cxx', 'c++': 'Cxx'})
+        if generate_function not in available_languages:
+            print(f'The language: {generate_function} is not available.')
+            tmp = ', '.join(sorted([lang for lang in set(available_languages.values())]))
+            print(f'Choose one of these: {tmp}.')
+            return
+        else:
+            language = available_languages[generate_function]
+    else:
+        language = None
+
+    ctf = make_ctf(parameters, discretize, table_size)
+    if language is not None and language in ['Cxx', 'Python']:
+        if language == 'Python':
+            generate_ctf_python(parameters, discretize, table_size)
+        else:
+            generate_ctf_cpp(parameters, discretize, table_size)
+
+    colors = vtkNamedColors()
+    colors.SetColor('ParaViewBkg', 82, 87, 110, 255)
+
+    sphere = vtkSphereSource()
+    sphere.SetThetaResolution(64)
+    sphere.SetPhiResolution(32)
+
+    cone = vtkConeSource()
+    cone.SetResolution(6)
+    cone.SetDirection(0, 1, 0)
+    cone.SetHeight(1)
+    cone.Update()
+    bounds = cone.GetOutput().GetBounds()
+
+    elevation_filter = vtkElevationFilter()
+    elevation_filter.SetLowPoint(0, bounds[2], 0)
+    elevation_filter.SetHighPoint(0, bounds[3], 0)
+    elevation_filter.SetInputConnection(cone.GetOutputPort())
+    # elevation_filter.SetInputConnection(sphere.GetOutputPort())
+
+    mapper = vtkPolyDataMapper()
+    mapper.SetInputConnection(elevation_filter.GetOutputPort())
+    mapper.SetLookupTable(ctf)
+    mapper.SetColorModeToMapScalars()
+    mapper.InterpolateScalarsBeforeMappingOn()
+
+    actor = vtkActor()
+    actor.SetMapper(mapper)
+    # actor.GetProperty().SetDiffuseColor(colors.GetColor3d('bisque'))
+
+    # Visualize
+    ren = vtkRenderer()
+    ren_win = vtkRenderWindow()
+    ren_win.AddRenderer(ren)
+    iren = vtkRenderWindowInteractor()
+    iren.SetRenderWindow(ren_win)
+
+    style = vtkInteractorStyleTrackballCamera()
+    iren.SetInteractorStyle(style)
+
+    ren.AddActor(actor)
+    ren.SetBackground(colors.GetColor3d('ParaViewBkg'))
+
+    ren_win.SetSize(640, 480)
+    ren_win.SetWindowName('ColorMapToLUT_XML')
+
+    ren_win.Render()
+    iren.Start()
+
+
+def parse_xml(fn_path):
+    """
+    Parse the XML file of a colormap.
+
+    Check out: https://sciviscolor.org/colormaps/ for some good XML files.
+    :param fn_path: The path to the XML file.
+    :return: The parameters for the color map.
+    """
+    with open(fn_path) as data_file:
+        xml_doc = etree.parse(data_file)
+    data_values = list()
+    color_values = list()
+    opacity_values = list()
+    nan = None
+    above = None
+    below = None
+
+    s = xml_doc.getroot().find('ColorMap')
+    if s is not None:
+        color_map_details = dict(s.attrib)
+    else:
+        color_map_details = None
+        sys.exit('The attribute "ColorMap" is not found.')
+    for s in xml_doc.getroot().findall('.//Point'):
+        data_values.append(s.attrib['x'])
+        color_values.append((s.attrib['r'], s.attrib['g'], s.attrib['b']))
+        opacity_values.append(s.attrib['o'])
+    s = xml_doc.getroot().find('.//NaN')
+    if s is not None:
+        nan = (s.attrib['r'], s.attrib['g'], s.attrib['b'])
+    s = xml_doc.getroot().find('.//Above')
+    if s is not None:
+        above = (s.attrib['r'], s.attrib['g'], s.attrib['b'])
+    s = xml_doc.getroot().find('.//Below')
+    if s is not None:
+        below = (s.attrib['r'], s.attrib['g'], s.attrib['b'])
+    return {'path': fn_path.name, 'color_map_details': color_map_details, 'data_values': data_values,
+            'color_values': color_values, 'opacity_values': opacity_values, 'NaN': nan, 'Above': above, 'Below': below}
+
+
+def make_ctf(parameters, discretize, table_size=None):
+    """
+    Generate the discretizable color transfer function
+    :param parameters: The parameters.
+    :param discretize: True if the values are to be mapped after discretization.
+    :param table_size: The table size.
+    :return: The discretizable color transfer function.
+    """
+
+    ctf = vtkDiscretizableColorTransferFunction()
+
+    interp_space = parameters['color_map_details'].get('interpolationspace', None)
+    if interp_space:
+        interp_space = interp_space.lower()
+        if interp_space == 'hsv':
+            ctf.SetColorSpaceToHSV()
+        elif interp_space == 'lab':
+            ctf.SetColorSpaceToLab()
+        elif interp_space == 'ciede2000':
+            ctf.SetColorSpaceToLabCIEDE2000()
+        elif interp_space == 'diverging':
+            ctf.SetColorSpaceToDiverging()
+        elif interp_space == 'step':
+            ctf.SetColorSpaceToStep()
+        else:
+            ctf.SetColorSpaceToRGB()
+    else:
+        ctf.SetColorSpaceToRGB()
+
+    scale = parameters['color_map_details'].get('interpolationtype', None)
+    if scale:
+        scale = scale.lower()
+        if scale == 'log10':
+            ctf.SetScaleToLog10()
+        else:
+            ctf.SetScaleToLinear()
+    else:
+        ctf.SetScaleToLinear()
+
+    if parameters['NaN'] is not None:
+        color = list(map(float, parameters['NaN']))
+        ctf.SetNanColor(*color)
+
+    if parameters['Above'] is not None:
+        color = list(map(float, parameters['Above']))
+        ctf.SetAboveRangeColor(*color)
+        ctf.UseAboveRangeColorOn()
+
+    if parameters['Below'] is not None:
+        color = list(map(float, parameters['Below']))
+        ctf.SetBelowRangeColor(*color)
+        ctf.UseBelowRangeColorOn()
+
+    space = parameters['color_map_details'].get('space', None)
+    if space:
+        space = space.lower()
+        for i in range(0, len(parameters['data_values'])):
+            color = list(map(float, parameters['color_values'][i]))
+            idx = float(parameters['data_values'][i])
+            if space == 'hsv':
+                ctf.AddHSVPoint(idx, *color)
+            else:
+                ctf.AddRGBPoint(idx, *color)
+
+    if table_size is not None:
+        ctf.SetNumberOfValues(table_size)
+    else:
+        ctf.SetNumberOfValues(len(parameters["data_values"]))
+
+    if discretize:
+        ctf.DiscretizeOn()
+    else:
+        ctf.DiscretizeOff()
+
+    return ctf
+
+
+def generate_ctf_python(parameters, discretize, table_size=None):
+    """
+    Generate a function do the ctf.
+
+    :param parameters: The parameters.
+    :param discretize: True if the values are to be mapped after discretization.
+    :param table_size: The table size.
+    :return: The discretizable color transfer function.
+    """
+    indent = ' ' * 4
+
+    comment = f'{indent}#'
+    if 'name' in parameters['color_map_details']:
+        comment += f' name: {parameters["color_map_details"]["name"]},'
+    if 'creator' in parameters['color_map_details']:
+        comment += f' creator: {parameters["color_map_details"]["creator"]},'
+    comment += f' file name: {parameters["path"]}'
+
+    s = ['', f'def get_ctf():', comment, f'{indent}ctf = vtkDiscretizableColorTransferFunction()', '']
+
+    interp_space = parameters['color_map_details'].get('interpolationspace', None)
+    if interp_space:
+        interp_space = interp_space.lower()
+        if interp_space == 'hsv':
+            s.append(f'{indent}ctf.SetColorSpaceToHSV()')
+        elif interp_space == 'lab':
+            s.append(f'{indent}ctf.SetColorSpaceToLab()')
+        elif interp_space == 'ciede2000':
+            s.append(f'{indent}ctf.SetColorSpaceToLabCIEDE2000()')
+        elif interp_space == 'diverging':
+            s.append(f'{indent}ctf.SetColorSpaceToDiverging()')
+        elif interp_space == 'step':
+            s.append(f'{indent}ctf.SetColorSpaceToStep()')
+        else:
+            s.append(f'{indent}ctf.SetColorSpaceToRGB()')
+    else:
+        s.append(f'{indent}ctf.SetColorSpaceToRGB()')
+
+    scale = parameters['color_map_details'].get('interpolationtype', None)
+    if scale:
+        scale = scale.lower()
+        if scale == 'log10':
+            s.append(f'{indent}ctf.SetScaleToLog10()')
+        else:
+            s.append(f'{indent}ctf.SetScaleToLinear()')
+    else:
+        s.append(f'{indent}ctf.SetScaleToLinear()')
+    s.append('')
+
+    if parameters['NaN'] is not None:
+        color = ', '.join(parameters['NaN'])
+        s.append(f'{indent}ctf.SetNanColor({color})')
+
+    if parameters['Above'] is not None:
+        color = ', '.join(parameters['Above'])
+        s.append(f'{indent}ctf.SetAboveRangeColor({color})')
+        s.append(f'{indent}ctf.UseAboveRangeColorOn()')
+
+    if parameters['Below'] is not None:
+        color = ', '.join(parameters['Below'])
+        s.append(f'{indent}ctf.SetBelowRangeColor({color})')
+        s.append(f'{indent}ctf.UseBelowRangeColorOn()')
+    s.append('')
+
+    space = parameters['color_map_details'].get('space', None)
+    if space:
+        space = space.lower()
+        for i in range(0, len(parameters['data_values'])):
+            color = ', '.join(parameters['color_values'][i])
+            idx = parameters['data_values'][i]
+            if space == 'hsv':
+                s.append(f'{indent}ctf.AddHSVPoint({idx}, {color})')
+            else:
+                s.append(f'{indent}ctf.AddRGBPoint({idx}, {color})')
+        s.append('')
+
+    if table_size is not None:
+        s.append(f'{indent}ctf.SetNumberOfValues({table_size})')
+    else:
+        s.append(f'{indent}ctf.SetNumberOfValues({len(parameters["data_values"])})')
+
+    if discretize:
+        s.append(f'{indent}ctf.DiscretizeOn()')
+    else:
+        s.append(f'{indent}ctf.DiscretizeOff()')
+    s.append('')
+
+    s.append(f'{indent}return ctf')
+    s.append('')
+
+    print('\n'.join(s))
+
+
+def generate_ctf_cpp(parameters, discretize, table_size=None):
+    """
+    Generate a function do the ctf.
+
+    :param parameters: The parameters.
+    :param discretize: True if the values are to be mapped after discretization.
+    :param table_size: The table size.
+    :return: The discretizable color transfer function.
+    """
+    indent = ' ' * 2
+
+    comment = f'{indent}//'
+    if 'name' in parameters['color_map_details']:
+        comment += f' name: {parameters["color_map_details"]["name"]},'
+    if 'creator' in parameters['color_map_details']:
+        comment += f' creator: {parameters["color_map_details"]["creator"]},'
+    comment += f' file name: {parameters["path"]}'
+
+    s = ['', f'vtkNew<vtkDiscretizableColorTransferFunction> getCTF()', '{', comment,
+         f'{indent}vtkNew<vtkDiscretizableColorTransferFunction> ctf;', '']
+
+    interp_space = parameters['color_map_details'].get('interpolationspace', None)
+    if interp_space:
+        interp_space = interp_space.lower()
+        if interp_space == 'hsv':
+            s.append(f'{indent}ctf->SetColorSpaceToHSV();')
+        elif interp_space == 'lab':
+            s.append(f'{indent}ctf->SetColorSpaceToLab();')
+        elif interp_space == 'ciede2000':
+            s.append(f'{indent}ctf->SetColorSpaceToLabCIEDE2000();')
+        elif interp_space == 'diverging':
+            s.append(f'{indent}ctf->SetColorSpaceToDiverging();')
+        elif interp_space == 'step':
+            s.append(f'{indent}ctf->SetColorSpaceToStep();')
+        else:
+            s.append(f'{indent}ctf->SetColorSpaceToRGB();')
+    else:
+        s.append(f'{indent}ctf->SetColorSpaceToRGB();')
+
+    scale = parameters['color_map_details'].get('interpolationtype', None)
+    if scale:
+        scale = scale.lower()
+        if scale == 'log10':
+            s.append(f'{indent}ctf->SetScaleToLog10();')
+        else:
+            s.append(f'{indent}ctf->SetScaleToLinear();')
+    else:
+        s.append(f'{indent}ctf->SetScaleToLinear();')
+    s.append('')
+
+    if parameters['NaN'] is not None:
+        color = ', '.join(parameters['NaN'])
+        s.append(f'{indent}ctf->SetNanColor({color});')
+
+    if parameters['Above'] is not None:
+        color = ', '.join(parameters['Above'])
+        s.append(f'{indent}ctf->SetAboveRangeColor({color});')
+        s.append(f'{indent}ctf->UseAboveRangeColorOn();')
+
+    if parameters['Below'] is not None:
+        color = ', '.join(parameters['Below'])
+        s.append(f'{indent}ctf->SetBelowRangeColor({color});')
+        s.append(f'{indent}ctf->UseBelowRangeColorOn();')
+    s.append('')
+
+    space = parameters['color_map_details'].get('space', None)
+    if space:
+        space = space.lower()
+        for i in range(0, len(parameters['data_values'])):
+            color = ', '.join(parameters['color_values'][i])
+            idx = parameters['data_values'][i]
+            if space == 'hsv':
+                s.append(f'{indent}ctf->AddHSVPoint({idx}, {color});')
+            else:
+                s.append(f'{indent}ctf->AddRGBPoint({idx}, {color});')
+        s.append('')
+
+    if table_size is not None:
+        s.append(f'{indent}ctf->SetNumberOfValues({table_size});')
+    else:
+        s.append(f'{indent}ctf->SetNumberOfValues({len(parameters["data_values"])});')
+
+    if discretize:
+        s.append(f'{indent}ctf->DiscretizeOn();')
+    else:
+        s.append(f'{indent}ctf->DiscretizeOff();')
+    s.append('')
+
+    s.append(f'{indent}return ctf;')
+    s.append('}')
+    s.append('')
+
+    print('\n'.join(s))
+
+
+if __name__ == '__main__':
+    file, discretise, size, generate = get_program_parameters(sys.argv)
+    main(file, discretise, size, generate)
diff --git a/src/Testing/Baseline/Cxx/Utilities/TestColorMapToLUT.png b/src/Testing/Baseline/Cxx/Utilities/TestColorMapToLUT.png
new file mode 100644
index 0000000000000000000000000000000000000000..055b93c5a6e64e306392b64d1160579e40cc0447
--- /dev/null
+++ b/src/Testing/Baseline/Cxx/Utilities/TestColorMapToLUT.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:4249f193946b010a87449b8594701ca350ce71515dd14eee6795fd1aeab5993a
+size 17274
diff --git a/src/Testing/Baseline/Python/Utilities/TestColorMapToLUT.png b/src/Testing/Baseline/Python/Utilities/TestColorMapToLUT.png
new file mode 100644
index 0000000000000000000000000000000000000000..055b93c5a6e64e306392b64d1160579e40cc0447
--- /dev/null
+++ b/src/Testing/Baseline/Python/Utilities/TestColorMapToLUT.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:4249f193946b010a87449b8594701ca350ce71515dd14eee6795fd1aeab5993a
+size 17274
diff --git a/src/Testing/Baseline/Python/Utilities/TestColorMapToLUT_JSON.png b/src/Testing/Baseline/Python/Utilities/TestColorMapToLUT_JSON.png
new file mode 100644
index 0000000000000000000000000000000000000000..055b93c5a6e64e306392b64d1160579e40cc0447
--- /dev/null
+++ b/src/Testing/Baseline/Python/Utilities/TestColorMapToLUT_JSON.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:4249f193946b010a87449b8594701ca350ce71515dd14eee6795fd1aeab5993a
+size 17274
diff --git a/src/Testing/Baseline/Python/Utilities/TestColorMapToLUT_XML.png b/src/Testing/Baseline/Python/Utilities/TestColorMapToLUT_XML.png
new file mode 100644
index 0000000000000000000000000000000000000000..055b93c5a6e64e306392b64d1160579e40cc0447
--- /dev/null
+++ b/src/Testing/Baseline/Python/Utilities/TestColorMapToLUT_XML.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:4249f193946b010a87449b8594701ca350ce71515dd14eee6795fd1aeab5993a
+size 17274
diff --git a/src/Testing/Data/Fast.json b/src/Testing/Data/Fast.json
new file mode 100644
index 0000000000000000000000000000000000000000..74c42a77c2ed52e9211728e0b1b4d1afb15447b5
--- /dev/null
+++ b/src/Testing/Data/Fast.json
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:39274855486e9c407ddf42f386916ec0fdc38fa3e847008107833d9ef87ddf51
+size 729
diff --git a/src/Testing/Data/Fast.xml b/src/Testing/Data/Fast.xml
new file mode 100644
index 0000000000000000000000000000000000000000..eda8879d54a0bbb5af94b767d391bd23d168e893
--- /dev/null
+++ b/src/Testing/Data/Fast.xml
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:78b3074991f0d47b6967466c089b54d516c82b0eefe2b57e13b1124d1915a6df
+size 1019