Skip to content


# ChooseTextColor

VTKEx/Cxx/Visualization/ChooseTextColor

### Description

This example uses a simple algorithm to choose a color that "contrasts" with another color. The ChooseContrastingColor procedure converts the input RGB value to HSV using vtkMath::RGBToHSV. If the value is <= .5, the light color is chosen as the contrasting color. Otherwise, the dark color is chosen. The default light color is white and the default dark color is black. Any color from vtkNamedColors can be specified for the light and dark colors.

To run the example with your own arguments:

    ChooseTextColor fontFile [background] [lightColor] [darkColor]

Info

VTKNamedColorPatches shows the availabel colors.

Info

The ChooseContrastingColor procedure is reusable, Cut and paste the declarations and code into other examples.

Tip

There are many sources of TrueType fonts. Here is one source.

Question

If you have a simple question about this example contact us at VTKExProject If your question is more complex and may require extended discussion, please use the VTK Discourse Forum

### Code

ChooseTextColor.cxx

    #include <vtkSmartPointer.h>

    #include <vtkMath.h>
    #include <vtkNamedColors.h>
    #include <vtkRenderWindow.h>
    #include <vtkRenderWindowInteractor.h>
    #include <vtkRenderer.h>
    #include <vtkTextActor.h>
    #include <vtkTextProperty.h>

    #include <sstream>
    #include <string>
    #include <vtksys/SystemTools.hxx>

    namespace {
    // Given a color, find a contrasting color. If the goven color is "light",
    // use the lightColor otherwise use the darkColor
    void ChooseContrastingColor(double* rgbIn, double* rgbOut,
                                const double threshold = .5,
                                const std::string& lightColor = "white",
                                const std::string& darkColor = "black");
    } // namespace

    int main(int argc, char* argv[])
    {
      if (argc < 2)
      {
        std::cerr << "Usage: " << argv[0]
                  << " font.ttf [backColor] [lightColor] [darkColor]" << std::endl;
        return EXIT_FAILURE;
      }

      // Defaults
      double threshold(.8);
      std::string backColor = "SlateGray";
      std::string lightColor = "White";
      std::string darkColor = "Black";
      if (argc > 2)
      {
        backColor = argv[2];
      }
      if (argc > 3)
      {
        lightColor = argv[3];
      }
      if (argc > 4)
      {
        darkColor = argv[4];
      }

      std::string fontFile(argv[1]);
      std::stringstream str;
      str << "Font: "
          << vtksys::SystemTools::GetFilenameWithoutExtension(std::string(argv[1]))
          << "\n"
          << "Background: " << backColor << "\n"
          << "Light Color: " << lightColor << "\n"
          << "Dark Color: " << darkColor;

      int width = 640;
      int height = 480;

      auto colors =
        vtkSmartPointer<vtkNamedColors>::New();

      auto actor =
        vtkSmartPointer<vtkTextActor>::New();
      actor->GetTextProperty()->SetJustificationToCentered();
      actor->GetTextProperty()->SetVerticalJustificationToCentered();
      actor->SetTextScaleModeToViewport();
      actor->SetInput(str.str().c_str());
      actor->SetPosition(width / 2, height / 2);
      actor->GetTextProperty()->BoldOff();
      actor->GetTextProperty()->SetFontSize(40);
      actor->GetTextProperty()->SetFontFamily(VTK_FONT_FILE);
      actor->GetTextProperty()->SetFontFile(fontFile.c_str());

      auto renderer =
        vtkSmartPointer<vtkRenderer>::New();
      renderer->SetBackground(colors->GetColor3d(backColor.c_str()).GetData());

      // Compute a good color for text on the renderer background
      double rgb[3];
      ChooseContrastingColor(renderer->GetBackground(), rgb, threshold, lightColor,
                             darkColor);
      std::cout << rgb[0] << "," << rgb[1] << "," << rgb[2] << std::endl;
      actor->GetTextProperty()->SetColor(rgb);

      auto renderWindow =
        vtkSmartPointer<vtkRenderWindow>::New();

      renderWindow->SetSize(width, height);
      renderWindow->AddRenderer(renderer);

      auto interactor =
        vtkSmartPointer<vtkRenderWindowInteractor>::New();
      interactor->SetRenderWindow(renderWindow);

      renderer->AddActor(actor);

      renderWindow->Render();
      interactor->Initialize();
      interactor->Start();

      return EXIT_SUCCESS;
    }

    namespace {
    void ChooseContrastingColor(double* rgbIn, double* rgbOut,
                                const double threshold,
                                const std::string& lightColor,
                                const std::string& darkColor)
    {
      auto colors =
        vtkSmartPointer<vtkNamedColors>::New();

      double hsv[3];
      // If the value is <= threshold, use a light color, otherwise use a dark color
      vtkMath::RGBToHSV(rgbIn, hsv);
      if (hsv[2] <= threshold)
      {
        colors->GetColor(lightColor.c_str(), rgbOut[0], rgbOut[1], rgbOut[2]);
      }
      else
      {
        colors->GetColor(darkColor.c_str(), rgbOut[0], rgbOut[1], rgbOut[2]);
      }
    }
    } // namespace

### CMakeLists.txt

    cmake_minimum_required(VERSION 3.3 FATAL_ERROR)

    project(ChooseTextColor)

    find_package(VTK COMPONENTS
      vtkvtkCommonColor
      vtkvtkCommonCore
      vtkvtkInteractionStyle
      vtkvtkRenderingContextOpenGL2
      vtkvtkRenderingCore
      vtkvtkRenderingFreeType
      vtkvtkRenderingGL2PSOpenGL2
      vtkvtkRenderingOpenGL2 QUIET)
    if (NOT VTK_FOUND)
      message("Skipping ChooseTextColor: ${VTK_NOT_FOUND_MESSAGE}")
      return ()
    endif()
    message (STATUS "VTK_VERSION: ${VTK_VERSION}")
    if (VTK_VERSION VERSION_LESS "8.90.0")
      # old system
      include(${VTK_USE_FILE})
      add_executable(ChooseTextColor MACOSX_BUNDLE ChooseTextColor.cxx )
      target_link_libraries(ChooseTextColor PRIVATE ${VTK_LIBRARIES})
    else ()
      # include all components
      add_executable(ChooseTextColor MACOSX_BUNDLE ChooseTextColor.cxx )
      target_link_libraries(ChooseTextColor PRIVATE ${VTK_LIBRARIES})
      # vtk_module_autoinit is needed
      vtk_module_autoinit(
        TARGETS ChooseTextColor
        MODULES ${VTK_LIBRARIES}
        )
    endif ()

### Download and Build ChooseTextColor

Click here to download ChooseTextColor and its CMakeLists.txt file. Once the tarball ChooseTextColor.tar has been downloaded and extracted,

    cd ChooseTextColor/build

If VTK is installed:

    cmake ..

If VTK is not installed but compiled on your system, you will need to specify the path to your VTK build:

    cmake -DVTK_DIR:PATH=/home/me/vtk_build ..

Build the project:

    make

and run it:

    ./ChooseTextColor

WINDOWS USERS

Be sure to add the VTK bin directory to your path. This will resolve the VTK dll's at run time.