A C++ library for generating qualitative color palettes with maximum perceptual distinctiveness, especially for data visualization. The API uses a builder-style interface for flexible palette configuration, supporting multiple input formats, color vision deficiency simulation, and perceptual color difference metrics.
Full documentation is available at https://jolars.github.io/qualpal/.
This library is also available as an R package called qualpalr, and as a web application at qualpal.cc.
- Automatic selection of color palettes using perceptual color difference metrics
- Color vision deficiency simulation for accessible palette design
- Multiple input formats: RGB values, hex strings, HSL ranges, built-in palettes
- Fast algorithms for large color spaces
- Builder-style C++ API for flexible palette configuration
- Web-Based Interface for simple and interactive color palette generation
- Features
- Motivation
- R Package
- Web App
- Quick Start
- Installation
- Usage Examples
- Contributing
- Versioning
- License
When visualizing categorical data, it is often necessary to select a set of distinct colors that are easily distinguishable from each other. This is especially important for accessibility, as many people have color vision deficiencies (CVD) that make it difficult to distinguish certain colors. qualpal aims to provide a simple and effective way to generate such color palettes, ensuring that the selected colors are not only distinct from each other, but also accessible to people with CVD.
The problem with almost all standard color palettes is that they are optimized for a specific number of colors. This is of course a problem by design, since a good 10-color palette has to be designed with the assumption that it will be used as a whole, not that it will be used in parts. But it means that if you want to select a subset of colors from a palette, you will not get the best possible result.
They are also often created by a human designer, which means that they may not be optimized for perceptual distinctiveness. qualpal, on the other hand, uses state-of-the art color difference metrics and a farthest-point sampling algorithm to select colors that are (approximately) maximally distinct from each other, while also considering color vision deficiencies.
The qualpal library is also available as an R package called qualpalr. This package is continuously updated to match the latest features of the C++ library, but may sometimes lag behind slightly. It provides a similar API for generating colors from R, making it easy to integrate qualpal into R workflows,
Qualpal is also available as a web application at qualpal.cc. The web app has slightly limited functionality compared to the library and R package, but it allows users to quickly generate color palettes directly in their browser.
Qualpal has been published in JOSS. You can read more about the motivation and design of qualpal in the paper. If you find qualpal useful in your research, please consider citing it (either using the DOI badge, the GitHub citation tool, or by referring directly to <CITATION.cff>.
Generate 5 colors from a HSL colorspace:
#include <qualpal.h>
using namespace qualpal;
Qualpal qp;
qp.setInputColorspace({ -170, 60 }, { 0, 0.7 }, { 0.2, 0.8 });
auto colorspace_pal = qp.generate(5);Select 2 colors from given RGB values:
qp.setInputRGB({ colors::RGB("#ff0000"),
colors::RGB("#00ff00"),
colors::RGB("#0000ff") });
auto rgb_pal = qp.generate(2);Consider color vision deficiency (CVD) when generating colors
qp.setInputPalette("ColorBrewer:Set2").setCvd({ { "deutan", 0.7 } });
auto cvd_pal = qp.generate(4);qualpal includes a powerful command line interface for palette generation and analysis. For a full list of options and usage examples, run:
qualpal --helpThere are also man pages available for the CLI:
man qualpalYou can also view the Doxygen-generated documentation for detailed CLI and API usage.
Generate 5 colors from the HSL color space, with full hue range, medium-high saturation (0.4-0.8), and medium lightness (0.3-0.7):
qualpal -n 5 -i colorspace "0:360" "0.4:0.8" "0.3:0.7"Select from hex colors:
qualpal -n 3 "#ff0000" "#00ff00" "#0000ff" "#ffff00"Extend existing palette (keep fixed colors provided after --extend):
qualpal -n 3 -i colorspace "0:180" "0.3:0.6" "0.7:0.9" --extend "#ff0000" "#00ff00"
Analyze palette with hex input:
qualpal analyze --input hex "#ffe402" "#ff5733" "#33ff57" "#3357ff"Color Difference Matrix (ciede2000 metric):
Colors analyzed: 4
Colors:
Idx Hex MinDist
0 #ffe402 29.52
1 #ff5733 49.57
2 #33ff57 29.52
3 #3357ff 50.07
Color Difference Matrix:
0 1 2 3
0 0.00 49.57 29.52 83.87
1 49.57 0.00 78.05 50.07
2 29.52 78.05 0.00 71.78
3 83.87 50.07 71.78 0.00
Pre-built packages are available for major Linux distributions from GitHub Releases.
# Automatic installation (detects your system)
curl -sSL https://raw.githubusercontent.com/jolars/qualpal/main/scripts/install.sh | bashDebian/Ubuntu:
# Download packages (replace with your architecture)
# For x86_64/amd64:
wget https://github.com/jolars/qualpal/releases/latest/download/libqualpal1_3.3.0_amd64.deb
wget https://github.com/jolars/qualpal/releases/latest/download/qualpal_3.3.0_amd64.deb
# For ARM64/aarch64:
wget https://github.com/jolars/qualpal/releases/latest/download/libqualpal1_3.3.0_arm64.deb
wget https://github.com/jolars/qualpal/releases/latest/download/qualpal_3.3.0_arm64.deb
# Install
sudo dpkg -i libqualpal1_*.deb qualpal_*.debRed Hat/Fedora/SUSE:
# Download packages (replace with your architecture)
# For x86_64:
wget https://github.com/jolars/qualpal/releases/latest/download/libqualpal1-3.3.0.x86_64.rpm
wget https://github.com/jolars/qualpal/releases/latest/download/qualpal-3.3.0.x86_64.rpm
# For ARM64/aarch64:
wget https://github.com/jolars/qualpal/releases/latest/download/libqualpal1-3.3.0.aarch64.rpm
wget https://github.com/jolars/qualpal/releases/latest/download/qualpal-3.3.0.aarch64.rpm
# Install
sudo rpm -i libqualpal1-*.rpm qualpal-*.rpmDevelopment Files: If you plan to develop with qualpal, also install the development package:
- Debian/Ubuntu:
libqualpal-dev_3.3.0_{amd64,arm64}.deb - Red Hat/Fedora/SUSE:
libqualpal-devel-3.3.0.{x86_64,aarch64}.rpm
- CMake >= 3.15
- C++17 compatible compiler (e.g., GCC, Clang, MSVC)
- [Optional] OpenMP for parallelization
- [Optional] help2man for CLI man page generation
- [Optional] Catch2 for testing
To build and install qualpal from source, you need to have CMake and a C++17 compatible C++ compiler installed. If you want the algorithm to be parallelized, you also need to have support for OpenMP.
To build, clone the repository and run the following commands:
git clone https://github.com/jolars/qualpal.git
cd qualpal
cmake -B build -S .
cmake --build build --config ReleaseIf you want to include the CLI interface, make sure to pass the
-DBUILD_CLI=ON option to CMake:
cmake -B build -S . -DBUILD_CLI=ONThen, to install the library (and CLI, if built), use the following command:
sudo cmake --install buildIf you prefer to install the library in a custom location, such as your home
directory, you can specify the --prefix option:
cmake --install build --prefix "$HOME/.local"Optionally, you can also run the CLI app directly from the build directory without installing it:
./build/qualpal --helpUnder your chosen prefix (e.g., $HOME/.local or /usr/local):
bin/qualpal- Command-line interface (whenBUILD_CLI=ON)include/qualpal/- C++ header fileslib/libqualpal.*(orlib64/libqualpal.*) - Library fileslib/cmake/qualpal/- CMake package configurationshare/doc/qualpal/LICENSE- License fileshare/man/man1/qualpal.1- Manual page
The binary packages are split into separate components:
- Runtime packages (
libqualpal1): Contains the shared library needed to run applications that use qualpal - CLI packages (
qualpal): Contains the command-line interface - depends on the runtime package - Development packages (
libqualpal-dev/libqualpal-devel): Contains headers, static library, and CMake files for building applications with qualpal
This separation allows you to install only what you need:
- Just want the CLI? Install runtime + CLI packages
- Developing with qualpal? Install all three packages
- Deploying an application? Install just the runtime package
To uninstall qualpal, we provide a CMake uninstall target. Run the following command:
cmake --build build --target uninstallUnix users can also delete the files directly by calling
xargs rm < build/install_manifest.txtTo build the WebAssembly package for web applications, you need to first install Emscripten.
Then, you can build the package with the following commands:
emcmake cmake -B build/wasm -S . -DBUILD_WASM=ON -DCMAKE_BUILD_TYPE=Release
emmake make -C build/wasm qualpal_wasmqualpal can be easily integrated into your CMake projects. After building and
installing the library, you can find it using CMake's find_package command.
find_package(qualpal REQUIRED)
target_link_libraries(your_target qualpal::qualpal)If you installed qualpal in a custom location, make sure to set the
CMAKE_PREFIX_PATH variable first to include the installation prefix, e.g.:
set(CMAKE_PREFIX_PATH "$ENV{HOME}/.local") # Or your custom prefix#include <iostream>
#include <qualpal.h>
using namespace qualpal;
int
main()
{
// Start with some input colors
Qualpal qp;
qp.setInputRGB({
colors::RGB("#e41a1c"), // Red
colors::RGB("#377eb8"), // Blue
colors::RGB("#4daf4a"), // Green
colors::RGB("#984ea3"), // Purple
colors::RGB("#ff7f00"), // Orange
});
// Select 3 most distinct colors
auto palette = qp.generate(3);
for (const auto& color : palette) {
std::cout << color.hex() << std::endl;
}
return 0;
}Adapt to deuteranomaly (red-green colorblindness) of severity 0.8:
Qualpal qp;
qp.setInputRGB(colors).setCvd({ { "deutan", 0.8 } });
auto accessible_palette = qp.generate(2);A soothing pastel palette, generated from a HSL color space:
Qualpal qp;
qp.setInputColorspace({ 20, 300 }, { 0.3, 0.7 }, { 0.7, 0.9 });
auto pastel_palette = qp.generate(5);When visualizing categorical data, consider a background color to ensure contrast:
auto pal = Qualpal{}
.setInputRGB({
colors::RGB("#f0f0f0"), // Light color (which we want to avoid)
colors::RGB("#e41a1c"), // Red
colors::RGB("#377eb8"), // Blue
colors::RGB("#4daf4a"), // Green
})
.setBackground(colors::RGB("#ffffff"))
.generate(3);Qualpal can take an existing color palette and improve it by selecting a subset of the most distinct colors from it, as well as ordering the result.
Here we design a CVD-friendly version of the "ColorBrewer:Set2" palette
for a black background, selecting 3 colors.
auto pal = Qualpal{}
.setInputPalette("ColorBrewer:Set2")
.setBackground(colors::RGB("#000000"))
.setCvd({ { "tritan", 0.2 }, { "deutan", 0.5 } })
.generate(3);Extend an existing palette by adding more distinct colors to it:
std::vector<colors::RGB> fixed = {
colors::RGB("#e41a1c"), // Red
colors::RGB("#377eb8"), // Blue
};
std::vector<colors::RGB> input = {
colors::RGB("#4daf4a"), // Green
colors::RGB("#984ea3"), // Purple
colors::RGB("#ff7f00"), // Orange
colors::RGB("#ffff33"), // Yellow
};
// Extend to 6 colors, keeping the first two fixed
auto ext_pal = Qualpal{}.setInputRGB(input).extend(fixed, 4);Contributions are welcome! Please see the CONTRIBUTING file for more information.
This project follows Semantic Versioning. Expect breaking changes in major releases, new features in minor releases, and bug fixes in patch releases.
MIT License - see LICENSE file.