From b002f217a3658e4bdd0c882046b7fc545f24113f Mon Sep 17 00:00:00 2001 From: Michael Migliore Date: Mon, 11 Mar 2024 10:15:33 +0100 Subject: [PATCH 1/8] Add colormap file support --- _config.yml | 11 +- application/CMakeLists.txt | 8 ++ application/F3DColorMapTools.cxx | 109 ++++++++++++++++++ application/F3DColorMapTools.h | 19 +++ application/F3DConfigFileTools.cxx | 6 +- application/F3DConfigFileTools.h | 1 - application/F3DOptionsParser.cxx | 5 +- application/F3DOptionsParser.h | 1 + application/F3DStarter.cxx | 22 ++++ application/testing/CMakeLists.txt | 14 +++ doc/dev/BUILD.md | 1 + doc/user/COLOR_MAPS.md | 41 +++++++ doc/user/CONFIGURATION_FILE.md | 4 +- doc/user/OPTIONS.md | 1 + library/public/image.h | 8 ++ library/src/image.cxx | 27 +++++ python/F3DPythonBindings.cxx | 3 +- python/testing/test_image.py | 5 + resources/colormaps/cividis.png | Bin 0 -> 259 bytes resources/colormaps/cubehelix.png | Bin 0 -> 309 bytes resources/colormaps/gist_earth.png | Bin 0 -> 303 bytes resources/colormaps/hot.png | Bin 0 -> 135 bytes resources/colormaps/inferno.png | Bin 0 -> 287 bytes resources/colormaps/licenses.md | 11 ++ resources/colormaps/magma.png | Bin 0 -> 273 bytes resources/colormaps/plasma.png | Bin 0 -> 273 bytes resources/colormaps/seismic.png | Bin 0 -> 136 bytes resources/colormaps/viridis.png | Bin 0 -> 269 bytes testing/baselines/TestColorMap16bits.png | 3 + testing/baselines/TestColorMap32bits.png | 3 + testing/baselines/TestColorMapFile.png | 3 + .../baselines/TestColorMapFileFullPath.png | 3 + testing/baselines/TestColorMapStem.png | 3 + testing/data/viridis16.png | 3 + testing/data/viridis32.hdr | 3 + testing/data/viridis8.png | 3 + testing/data/white_grayscale.png | 3 + 37 files changed, 313 insertions(+), 11 deletions(-) create mode 100644 application/F3DColorMapTools.cxx create mode 100644 application/F3DColorMapTools.h create mode 100644 doc/user/COLOR_MAPS.md create mode 100644 resources/colormaps/cividis.png create mode 100644 resources/colormaps/cubehelix.png create mode 100644 resources/colormaps/gist_earth.png create mode 100644 resources/colormaps/hot.png create mode 100644 resources/colormaps/inferno.png create mode 100644 resources/colormaps/licenses.md create mode 100644 resources/colormaps/magma.png create mode 100644 resources/colormaps/plasma.png create mode 100644 resources/colormaps/seismic.png create mode 100644 resources/colormaps/viridis.png create mode 100644 testing/baselines/TestColorMap16bits.png create mode 100644 testing/baselines/TestColorMap32bits.png create mode 100644 testing/baselines/TestColorMapFile.png create mode 100644 testing/baselines/TestColorMapFileFullPath.png create mode 100644 testing/baselines/TestColorMapStem.png create mode 100644 testing/data/viridis16.png create mode 100644 testing/data/viridis32.hdr create mode 100644 testing/data/viridis8.png create mode 100644 testing/data/white_grayscale.png diff --git a/_config.yml b/_config.yml index 79d3b46aa6..e342687fe4 100644 --- a/_config.yml +++ b/_config.yml @@ -112,18 +112,25 @@ defaults: - scope: - path: "doc/user/DESKTOP_INTEGRATION.md" + path: "doc/user/COLOR_MAPS.md" values: parent: User Documentation nav_order: 5 + - + scope: + path: "doc/user/DESKTOP_INTEGRATION.md" + values: + parent: User Documentation + nav_order: 6 + - scope: path: "doc/user/LIMITATIONS_AND_TROUBLESHOOTING.md" values: title: Limitations and Troubleshooting parent: User Documentation - nav_order: 6 + nav_order: 7 # libf3d doc - diff --git a/application/CMakeLists.txt b/application/CMakeLists.txt index 13ff60e894..fa1660b1f1 100644 --- a/application/CMakeLists.txt +++ b/application/CMakeLists.txt @@ -10,6 +10,7 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/F3DConfig.h.in" "${CMAKE_CURRENT_BINARY_DIR}/F3DConfig.h") set(F3D_SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/F3DColorMapTools.cxx ${CMAKE_CURRENT_SOURCE_DIR}/F3DConfigFileTools.cxx ${CMAKE_CURRENT_BINARY_DIR}/F3DIcon.cxx ${CMAKE_CURRENT_SOURCE_DIR}/F3DOptionsParser.cxx @@ -209,6 +210,13 @@ install( COMPONENT configuration EXCLUDE_FROM_ALL) +# Default color maps +install( + DIRECTORY "${F3D_SOURCE_DIR}/resources/colormaps/" + DESTINATION "${f3d_config_dir}/colormaps" + COMPONENT colormaps + EXCLUDE_FROM_ALL) + # Other ressoure files if(UNIX AND NOT APPLE AND NOT ANDROID) install(FILES "${F3D_SOURCE_DIR}/resources/f3d.desktop" diff --git a/application/F3DColorMapTools.cxx b/application/F3DColorMapTools.cxx new file mode 100644 index 0000000000..34194db973 --- /dev/null +++ b/application/F3DColorMapTools.cxx @@ -0,0 +1,109 @@ +#include "F3DColorMapTools.h" + +#include "F3DConfigFileTools.h" + +#include "image.h" +#include "log.h" + +#include + +namespace fs = std::filesystem; + +namespace F3DColorMapTools +{ +std::string Find(const std::string& str) +{ + if (fs::exists(str)) + { + fs::path resolved = fs::canonical(str); + if (fs::is_regular_file(resolved)) + { + // already full path + return resolved.string(); + } + } + + fs::path cmPath; + try + { + std::vector dirsToCheck; + dirsToCheck.emplace_back(F3DConfigFileTools::GetUserConfigFileDirectory() / "colormaps"); +#ifdef __APPLE__ + dirsToCheck.emplace_back("/usr/local/etc/f3d/colormaps"); +#endif +#ifdef __linux__ + dirsToCheck.emplace_back("/etc/f3d/colormaps"); + dirsToCheck.emplace_back("/usr/share/f3d/colormaps"); +#endif + dirsToCheck.emplace_back(F3DConfigFileTools::GetBinaryConfigFileDirectory() / "colormaps"); + + for (const fs::path& dir : dirsToCheck) + { + // If the string is a stem, add extension + if (fs::path(str).stem() == str) + { + cmPath = dir / (str + ".png"); + } + else + { + // If not, use directly + cmPath = dir / str; + } + + if (fs::exists(cmPath)) + { + return cmPath.string(); + } + } + + return {}; + } + catch (const fs::filesystem_error&) + { + f3d::log::error("Error recovering color map file path: ", str); + return {}; + } + + return {}; +} + +std::vector Read(const std::string& path) +{ + try + { + f3d::image img(path); + + if (img.getChannelCount() < 3) + { + f3d::log::error("The specified color map must have at least 3 channels"); + return {}; + } + + if (img.getHeight() != 1) + { + f3d::log::warn("The specified color map height is not equal to 1, only the first row is " + "taken into account"); + } + + int w = img.getWidth(); + + std::vector cm(4 * w); + + for (int i = 0; i < w; i++) + { + std::vector pixel = img.getNormalizedPixel({ i, 0 }); + cm[4 * i + 0] = static_cast(i) / (w - 1); + cm[4 * i + 1] = pixel[0]; + cm[4 * i + 2] = pixel[1]; + cm[4 * i + 3] = pixel[2]; + } + + return cm; + } + catch (const f3d::image::read_exception&) + { + f3d::log::error("Cannot read colormap at ", path); + return {}; + } +} +} diff --git a/application/F3DColorMapTools.h b/application/F3DColorMapTools.h new file mode 100644 index 0000000000..8641898853 --- /dev/null +++ b/application/F3DColorMapTools.h @@ -0,0 +1,19 @@ +/** + * @class F3DColorMapReader + * @brief A namespace used to convert images to libf3d colormap option + * + */ + +#ifndef F3DColorMapReader_h +#define F3DColorMapReader_h + +#include +#include + +namespace F3DColorMapTools +{ +std::string Find(const std::string& str); +std::vector Read(const std::string& path); +} + +#endif diff --git a/application/F3DConfigFileTools.cxx b/application/F3DConfigFileTools.cxx index 780e548ef8..00e6740b6f 100644 --- a/application/F3DConfigFileTools.cxx +++ b/application/F3DConfigFileTools.cxx @@ -59,9 +59,9 @@ fs::path F3DConfigFileTools::GetBinaryConfigFileDirectory() // Add binary specific paths #if F3D_MACOS_BUNDLE - dirPath /= "Resources/configs"; + dirPath /= "Resources"; #else - dirPath /= "share/f3d/configs"; + dirPath /= "share/f3d"; #endif } catch (const fs::filesystem_error&) @@ -88,7 +88,7 @@ fs::path F3DConfigFileTools::GetConfigPath(const std::string& configSearch) dirsToCheck.emplace_back("/etc/f3d"); dirsToCheck.emplace_back("/usr/share/f3d/configs"); #endif - dirsToCheck.emplace_back(F3DConfigFileTools::GetBinaryConfigFileDirectory()); + dirsToCheck.emplace_back(F3DConfigFileTools::GetBinaryConfigFileDirectory() / "configs"); for (const fs::path& dir : dirsToCheck) { diff --git a/application/F3DConfigFileTools.h b/application/F3DConfigFileTools.h index 1714f23f12..60c5a766eb 100644 --- a/application/F3DConfigFileTools.h +++ b/application/F3DConfigFileTools.h @@ -14,7 +14,6 @@ namespace F3DConfigFileTools { std::filesystem::path GetUserConfigFileDirectory(); std::filesystem::path GetBinaryConfigFileDirectory(); -std::filesystem::path GetSystemConfigFileDirectory(); std::filesystem::path GetConfigPath(const std::string& configSearch); } diff --git a/application/F3DOptionsParser.cxx b/application/F3DOptionsParser.cxx index fa766bf8c1..6e3cf7dfa0 100644 --- a/application/F3DOptionsParser.cxx +++ b/application/F3DOptionsParser.cxx @@ -307,9 +307,9 @@ void ConfigurationOptions::GetOptions(F3DAppOptions& appOptions, f3d::options& o this->DeclareOption(grp0, "help", "h", "Print help"); this->DeclareOption(grp0, "version", "", "Print version details"); this->DeclareOption(grp0, "readers-list", "", "Print the list of readers"); - this->DeclareOption(grp0, "config", "", "Specify the configuration file to use. absolute/relative path or filename/filestem to search in configuration file locations.", appOptions.UserConfigFile, LocalHasDefaultNo, MayHaveConfig::NO , ""); + this->DeclareOption(grp0, "config", "", "Specify the configuration file to use. absolute/relative path or filename/filestem to search in configuration file locations.", appOptions.UserConfigFile, LocalHasDefaultNo, MayHaveConfig::NO, ""); this->DeclareOption(grp0, "dry-run", "", "Do not read the configuration file", appOptions.DryRun, HasDefault::YES, MayHaveConfig::NO ); - this->DeclareOption(grp0, "no-render", "", "Do not render anything and quit right after loading the first file, use with --verbose to recover information about a file.", appOptions.NoRender, HasDefault::YES, MayHaveConfig::YES ); + this->DeclareOption(grp0, "no-render", "", "Do not render anything and quit right after loading the first file, use with --verbose to recover information about a file.", appOptions.NoRender, HasDefault::YES, MayHaveConfig::YES); this->DeclareOption(grp0, "max-size", "", "Maximum size in Mib of a file to load, negative value means unlimited", appOptions.MaxSize, HasDefault::YES, MayHaveConfig::YES, ""); this->DeclareOption(grp0, "watch", "", "Watch current file and automatically reload it whenever it is modified on disk", appOptions.Watch, HasDefault::YES, MayHaveConfig::YES ); this->DeclareOption(grp0, "load-plugins", "", "List of plugins to load separated with a comma", appOptions.Plugins, LocalHasDefaultNo, MayHaveConfig::YES, ""); @@ -380,6 +380,7 @@ void ConfigurationOptions::GetOptions(F3DAppOptions& appOptions, f3d::options& o this->DeclareOption(grp4, "cells", "c", "Use a scalar array from the cells", options.getAsBoolRef("model.scivis.cells"), HasDefault::YES, MayHaveConfig::YES); this->DeclareOption(grp4, "range", "", "Custom range for the coloring by array", options.getAsDoubleVectorRef("model.scivis.range"), HasDefault::YES, MayHaveConfig::YES, ""); this->DeclareOption(grp4, "bar", "b", "Show scalar bar", options.getAsBoolRef("ui.bar"), HasDefault::YES, MayHaveConfig::YES); + this->DeclareOption(grp4, "colormap-file", "", "Specify a colormap image (ignored if \"colormap\" is specified)", appOptions.ColorMapFile, LocalHasDefaultNo, MayHaveConfig::YES, ""); this->DeclareOption(grp4, "colormap", "", "Specify a custom colormap", options.getAsDoubleVectorRef("model.scivis.colormap"), HasDefault::YES, MayHaveConfig::YES, ""); this->DeclareOption(grp4, "volume", "v", "Show volume if the file is compatible", options.getAsBoolRef("model.volume.enable"), HasDefault::YES, MayHaveConfig::YES); this->DeclareOption(grp4, "inverse", "i", "Inverse opacity function for volume rendering", options.getAsBoolRef("model.volume.inverse"), HasDefault::YES, MayHaveConfig::YES); diff --git a/application/F3DOptionsParser.h b/application/F3DOptionsParser.h index 50ce83204f..b085428d2c 100644 --- a/application/F3DOptionsParser.h +++ b/application/F3DOptionsParser.h @@ -20,6 +20,7 @@ class options; struct F3DAppOptions { std::string UserConfigFile = ""; + std::string ColorMapFile = ""; bool DryRun = false; bool GeometryOnly = false; bool GroupGeometries = false; diff --git a/application/F3DStarter.cxx b/application/F3DStarter.cxx index 5bda6a197f..5d01980954 100644 --- a/application/F3DStarter.cxx +++ b/application/F3DStarter.cxx @@ -1,5 +1,6 @@ #include "F3DStarter.h" +#include "F3DColorMapTools.h" #include "F3DConfig.h" #include "F3DIcon.h" #include "F3DNSDelegate.h" @@ -339,6 +340,27 @@ int F3DStarter::Start(int argc, char** argv) } #endif } + + // Parse colormap + if (!this->Internals->AppOptions.ColorMapFile.empty()) + { + std::string fullPath = F3DColorMapTools::Find(this->Internals->AppOptions.ColorMapFile); + + if (!fullPath.empty()) + { + auto cm = F3DColorMapTools::Read(fullPath); + + if (!cm.empty()) + { + this->Internals->Engine->getOptions().set("model.scivis.colormap", cm); + } + } + else + { + f3d::log::error("Cannot find the colormap ", this->Internals->AppOptions.ColorMapFile); + } + } + f3d::log::debug("Engine configured"); f3d::log::debug("========== Loading 3D file =========="); diff --git a/application/testing/CMakeLists.txt b/application/testing/CMakeLists.txt index 1ba7fef5d4..b5b55c0c8d 100644 --- a/application/testing/CMakeLists.txt +++ b/application/testing/CMakeLists.txt @@ -201,6 +201,20 @@ f3d_test(NAME TestConfigOrder DATA suzanne.ply ARGS CONFIG ${F3D_SOURCE_DIR}/tes f3d_test(NAME TestOutputStream DATA suzanne.ply ARGS --verbose=quiet --output=- REGEXP "^.PNG" NO_BASELINE NO_OUTPUT) f3d_test(NAME TestOutputStreamInfo DATA suzanne.ply ARGS --verbose=info --output=- REGEXP "redirected to stderr" NO_BASELINE NO_OUTPUT) +# Color map files testing +f3d_test(NAME TestColorMapFileFullPath DATA dragon.vtu ARGS --colormap-file=${F3D_SOURCE_DIR}/testing/data/viridis8.png --scalars --comp=1 DEFAULT_LIGHTS) +f3d_test(NAME TestColorMapInvalid DATA dragon.vtu ARGS --colormap-file=${F3D_SOURCE_DIR}/testing/data/invalid.png --scalars REGEXP "Cannot read colormap at" NO_BASELINE) +f3d_test(NAME TestColorMapNonExistent DATA dragon.vtu ARGS --colormap-file=${F3D_SOURCE_DIR}/testing/data/non_existent.png --scalars REGEXP "Cannot find the colormap" NO_BASELINE) +f3d_test(NAME TestColorMapGrayscale DATA dragon.vtu ARGS --colormap-file=${F3D_SOURCE_DIR}/testing/data/white_grayscale.png --scalars REGEXP "The specified color map must have at least 3 channels" NO_BASELINE) +f3d_test(NAME TestColorMapMore1pxWarning DATA dragon.vtu ARGS --verbose=warning --colormap-file=${F3D_SOURCE_DIR}/testing/data/16bit.png --scalars REGEXP "The specified color map height is not equal to 1" NO_BASELINE) +f3d_test(NAME TestColorMap16bits DATA dragon.vtu ARGS --colormap-file=${F3D_SOURCE_DIR}/testing/data/viridis16.png --scalars --comp=1 DEFAULT_LIGHTS) +f3d_test(NAME TestColorMap32bits DATA dragon.vtu ARGS --colormap-file=${F3D_SOURCE_DIR}/testing/data/viridis32.hdr --scalars --comp=1 DEFAULT_LIGHTS) +if(NOT F3D_MACOS_BUNDLE) + file(COPY "${F3D_SOURCE_DIR}/resources/colormaps/" DESTINATION "${CMAKE_BINARY_DIR}/share/f3d/colormaps") + f3d_test(NAME TestColorMapStem DATA dragon.vtu ARGS --colormap-file=magma --scalars --comp=1 DEFAULT_LIGHTS) + f3d_test(NAME TestColorMapFile DATA dragon.vtu ARGS --colormap-file=magma.png --scalars --comp=1 DEFAULT_LIGHTS) +endif() + # Needs SSBO: https://gitlab.kitware.com/vtk/vtk/-/merge_requests/10675 if(VTK_VERSION VERSION_GREATER_EQUAL 9.3.20231108) if(APPLE) # MacOS does not support OpenGL 4.3 diff --git a/doc/dev/BUILD.md b/doc/dev/BUILD.md index c4bca6b3de..5d2c3c20b0 100644 --- a/doc/dev/BUILD.md +++ b/doc/dev/BUILD.md @@ -90,3 +90,4 @@ Name|Installed by default|Operating system|Description `java`|YES|ALL|Java bindings. `mimetypes`|NO|Linux|Plugins mimetype XML files for integration with Freedesktop. `assets`|YES|Linux|Assets for integration with Freedesktop. +`colormaps`|NO|ALL|Color maps presets, see [documentation](../user/COLOR_MAPS.md) diff --git a/doc/user/COLOR_MAPS.md b/doc/user/COLOR_MAPS.md new file mode 100644 index 0000000000..4d2b65e980 --- /dev/null +++ b/doc/user/COLOR_MAPS.md @@ -0,0 +1,41 @@ +# Color maps + +## Image files + +It is possible to specify a color map using the `--colormap-file` option. +The value of the option can be a full path to an image file, a filename only is which case, these directories are used to find the file (in this order): + * Linux: `${XDG_CONFIG_HOME}/f3d/colormaps`, `~/.config/f3d/colormaps`, `/etc/f3d/colormaps`, `/usr/share/f3d/colormaps`, `[install_dir]/share/f3d/colormaps` + * Windows: `%APPDATA%\f3d\colormaps`, `[install_dir]\share\f3d\configs\colormaps` + * macOS: `${XDG_CONFIG_HOME}/f3d/colormaps`, `~/.config/f3d/colormaps`, `/usr/local/etc/f3d/colormaps`, `f3d.app/Contents/Resources/configs/colormaps` +In case the filename omits the extension, PNG files only are searched. + +We provide some ready to use color maps files, listed in the table below: + +Name|Image +------|------ +cividis| +cubehelix| +gist_earth| +hot| +inferno| +magma| +plasma| +seismic| +viridis| + +It is possible to create a custom color map by creating a simple RGB image in any supported format (PNG recommended), and any resolution (if the height is more than 1 row, only the first one is taken into account). The image must be copied in the user config directory: +* Linux/macOS: `~/.config/f3d/colormaps` +* Windows: `%APPDATA%\f3d\colormaps` + +## Custom values + +It is also possible to set values manually using `--colormap` option. A list of numbers between 0 and 1 must be specified. The size of the list is a multiple of 4 and each 4-components tuple correspond to the scalar value, followed by the RGB color. +For example, the default value corresponds to the `hot` preset which can be defined manually with `--colormap=0.0,0.0,0.0,0.0,0.4,0.9,0.0,0.0,0.8,0.9,0.9,0.0,1.0,1.0,1.0,1.0` which consists of 4 tuples: +Value|RGB +------|------ +0.0| 0.0, 0.0, 0.0 +0.4| 0.9, 0.0, 0.0 +0.8| 0.9, 0.9, 0.0 +1.0| 1.0, 1.0, 1.0 + +Values in between are interpolated. diff --git a/doc/user/CONFIGURATION_FILE.md b/doc/user/CONFIGURATION_FILE.md index 801cb74101..67104ef1f1 100644 --- a/doc/user/CONFIGURATION_FILE.md +++ b/doc/user/CONFIGURATION_FILE.md @@ -68,9 +68,9 @@ off on the command line if needed, eg: `--point-sprites=false`. The configuration file or directory possible locations depends on your operating system. They are considered in the below order and only the first found will be used. - * Linux: `${XDG_CONFIG_HOME}/.config/f3d/config(.json,.d)`, `~/.config/f3d/config(.json,d)`, `/etc/f3d/config(.json,.d)`, `/usr/share/f3d/configs/config(.json,.d)`, `[install_dir]/share/f3d/configs/config(.json,.d)` + * Linux: `${XDG_CONFIG_HOME}/f3d/config(.json,.d)`, `~/.config/f3d/config(.json,d)`, `/etc/f3d/config(.json,.d)`, `/usr/share/f3d/configs/config(.json,.d)`, `[install_dir]/share/f3d/configs/config(.json,.d)` * Windows: `%APPDATA%\f3d\(config.json,.d)`, `[install_dir]\share\f3d\configs\(config.json,.d)` - * macOS: `${XDG_CONFIG_HOME}/.config/f3d/config(.json,.d)`, `~/.config/f3d/config(.json,.d)`, `/usr/local/etc/f3d/config(.json,.d)`, `f3d.app/Contents/Resources/configs/config(.json,.d)` + * macOS: `${XDG_CONFIG_HOME}/f3d/config(.json,.d)`, `~/.config/f3d/config(.json,.d)`, `/usr/local/etc/f3d/config(.json,.d)`, `f3d.app/Contents/Resources/configs/config(.json,.d)` The binary release will install the default config directory. On Linux, they will be installed in `[install_dir]/share/f3d/configs/`, on Windows, they will be installed in `[install_dir]\share\f3d\configs\`, on macOS, it will be installed in the bundle. diff --git a/doc/user/OPTIONS.md b/doc/user/OPTIONS.md index 3a3b69dae9..1f04904113 100644 --- a/doc/user/OPTIONS.md +++ b/doc/user/OPTIONS.md @@ -84,6 +84,7 @@ Options|Default|Description -c, \-\-cells||Specify that the scalar array is to be found *on the cells* instead of on the points.
Use with the scalar option. \-\-range=\||Set a *custom range for the coloring* by the array.
Use with the scalar option. -b, \-\-bar||Show *scalar bar* of the coloring by array.
Use with the scalar option. +\-\-colormap\-file=\||Set a *colormap file for the coloring*.
See [color maps](COLOR_MAPS.md).
Use with the scalar option. \-\-colormap=\||Set a *custom colormap for the coloring*.
This is a list of colors in the format `val1,red1,green1,blue1,...,valN,redN,greenN,blueN`
where all values are in the range (0,1).
Use with the scalar option. -v, \-\-volume||Enable *volume rendering*. It is only available for 3D image data (vti, dcm, nrrd, mhd files) and will display nothing with other formats. -i, \-\-inverse||Inverse the linear opacity function used for volume rendering. diff --git a/library/public/image.h b/library/public/image.h index 7aa1d90dd9..3dcd593017 100644 --- a/library/public/image.h +++ b/library/public/image.h @@ -85,6 +85,14 @@ class F3D_EXPORT image bool operator!=(const image& reference) const; ///@} + /** + * Read one specific pixel and return all channel normalized values. + * If the channel type is BYTE or SHORT, the values are normalized to [0, 1] range. + * \warning Because of the normalization, this function can be slow, prefer getContent when + * reading several pixels and normalization is not needed. + */ + std::vector getNormalizedPixel(const std::pair& xy) const; + /** * Get the list of supported image format when opening a file. */ diff --git a/library/src/image.cxx b/library/src/image.cxx index b639c8618e..52c0b8f339 100644 --- a/library/src/image.cxx +++ b/library/src/image.cxx @@ -353,6 +353,33 @@ bool image::operator!=(const image& reference) const return !this->operator==(reference); } +//---------------------------------------------------------------------------- +std::vector image::getNormalizedPixel(const std::pair& xy) const +{ + std::vector pixel(this->getChannelCount()); + + for (size_t i = 0; i < pixel.size(); i++) + { + double v = this->Internals->Image->GetScalarComponentAsDouble( + xy.first, xy.second, 0, static_cast(i)); + + switch (this->getChannelType()) + { + case ChannelType::BYTE: + pixel[i] = v / 255.0; + break; + case ChannelType::SHORT: + pixel[i] = v / 65535.0; + break; + default: + pixel[i] = v; + break; + } + } + + return pixel; +} + //---------------------------------------------------------------------------- void image::save(const std::string& path, SaveFormat format) const { diff --git a/python/F3DPythonBindings.cxx b/python/F3DPythonBindings.cxx index 25d258ae68..0830179272 100644 --- a/python/F3DPythonBindings.cxx +++ b/python/F3DPythonBindings.cxx @@ -147,7 +147,8 @@ PYBIND11_MODULE(pyf3d, module) throw py::key_error(key); } }) - .def("all_metadata", &f3d::image::allMetadata); + .def("all_metadata", &f3d::image::allMetadata) + .def("normalized_pixel", &f3d::image::getNormalizedPixel); // f3d::options py::class_ options(module, "Options"); diff --git a/python/testing/test_image.py b/python/testing/test_image.py index 557b042870..60dc5bc711 100644 --- a/python/testing/test_image.py +++ b/python/testing/test_image.py @@ -71,6 +71,11 @@ def test_formats(f3d_engine): assert ".png" in formats +def test_normalized_pixel(f3d_engine): + img = f3d_engine.window.render_to_image() + assert img.normalized_pixel((0, 0)) == [0.2, 0.2, 0.2] + + @pytest.mark.parametrize( "img_filename", [ diff --git a/resources/colormaps/cividis.png b/resources/colormaps/cividis.png new file mode 100644 index 0000000000000000000000000000000000000000..3f27f1f4bf0a4460a50e93c36cd7917fdcb306f2 GIT binary patch literal 259 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K57&+L0q+w)1Igr}m>EaktF=y%|Pa$SS9_HPi zag*4e{$DTooWb?XjFUwR1SU<0)ag%Oknp;>MKr@x`pyySH~|NdcZYgkY%XA)l`N32 zW8z@_{DY-QXNzV;@>B7*?tiY!b-R7sdDhMTnc>#S`D<=IOV@p0oD!D5&fhY9@BCxm z&8_#l|Jwbk^R?9UdBN8v$#UN}i}`qVpJlduMe?^-Q}3KH=lvQ@dJKzSOg{m!;AOWxyP?5 zpPu~DFe;m~vUYDho1?S7$&)WH1O3cw`+EaktF{gE+XWwB19+uS} z34ELr`p^8|pMKVHinBJ~GldPi?_6=>=K0AQcY?W+$^S{GjY6HlK?WxtgT@6frRALT zd@twioqYCh^gr$L(+zcxOQ#*pE#L6{TBLXUrzUoz1A$vB*$pl%&ib7GZ{EpgvIj1H z%lOx)`@e9%W5EPIrF#&=u<0RV=KrOY literal 0 HcmV?d00001 diff --git a/resources/colormaps/hot.png b/resources/colormaps/hot.png new file mode 100644 index 0000000000000000000000000000000000000000..29b687ac6b04680df0c5b585827b4736b369e762 GIT binary patch literal 135 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K57&+L0q+w)1Igm2(ba4!+n3Mb@E#b%cBL@x~ zICJ0t!{Wk??oU^$+pmyu*8h3%nVMS~8ylOL&5Q{)iZ(yKGBfnYGyi+ctQH2;&zBnE dnda-upao=e05J$$3Z4w2JYD@<);T3K0RSwzChGtI literal 0 HcmV?d00001 diff --git a/resources/colormaps/inferno.png b/resources/colormaps/inferno.png new file mode 100644 index 0000000000000000000000000000000000000000..2e5f991034a81395c10a6e59b40a586703ea1f47 GIT binary patch literal 287 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K57&+L0q+w)1IgmQz>EaktF=y)Ji|Y<6@HqGL ze*gb}$4zEWuDd30?H1fP&Z)4KBaNexMIv!R^y)2czt^!#dmM{i-<=$@#zy;daJ#jB z{uH0t;dcu%r>1{i;J#Ih{ou9Z$9~wq*0D>uSiF`|^ON6qpN-#j_HDRvuCLVZwZ(Uv zG_(0%XJ~#~JdOGFuG-BGM{CnAeVzL8O<}|O`KEQ>E8ZTT$o~3z|DPROr<`~EJ}KDx z`a0hm4?ZUBmTy^=UQ)m1e@ObPHM34WOPW1h?MHs7?-ZX|5ygA`ecv49&VQ7*V8?8K jkSF<4BRtc5eHpZXYz~kB5L^nL45B<;{an^LB{Ts5u^D|y literal 0 HcmV?d00001 diff --git a/resources/colormaps/licenses.md b/resources/colormaps/licenses.md new file mode 100644 index 0000000000..d3412b5786 --- /dev/null +++ b/resources/colormaps/licenses.md @@ -0,0 +1,11 @@ +|Name |Author |License | +|----------|----------------------------------------------------|------------| +|cividis |Jamie Nunez |BSD-3-Clause| +|cubehelix | |BSD-2-Clause| +|gist_earth|David Munro |BSD-3-Clause| +|hot | |PSF | +|inferno |Nathaniel J. Smith, Stefan van der Walt |CC0 | +|magma |Nathaniel J. Smith, Stefan van der Walt |CC0 | +|plasma |Nathaniel J. Smith, Stefan van der Walt |CC0 | +|seismic | |PSF | +|viridis |Nathaniel J. Smith, Stefan van der Walt, Eric Firing|CC0 | diff --git a/resources/colormaps/magma.png b/resources/colormaps/magma.png new file mode 100644 index 0000000000000000000000000000000000000000..efdeaabad62c1f5d6ebfe6bd4f57c720abea6c19 GIT binary patch literal 273 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K57&+L0q+w)1Igr}t>EaktF(-GDH`5UV4yVR* zf7id!`Lli9Cl(XmASQcdjtLAb>6XC^aub+Ve=E&8JMZeH`A?^}KVf(IqOfBNyOC(R z--Qc%CtrKBT*8O#uxu(y{(;oczd$E z^`@}R`);27DLZ+lAMpDk?7TYCOa_~xaVXJ>qs|FJ=D=ld5M>w!MuOO5bM^YvxW0EaktF{gEscM*#skMn%n z**Qh;=2UrY&PZnQ^%oP_WVfwbsjmLtm!J=e`X;HISjFyVSU5L>NAtOXf1+gDxwbOC z$Li*$9K3no4QwCxtz|Rv+rCCjaH{Sc#)~)d1v4$=3f|o+-E+J*ded^5{$KS!&$T^> zzW42sqy5Lt&!=sVyz%cI^X%Jy9xeP`JY##t&gylw{&G2Kujei=EMED`K>K{f?$<5cBs*2uRFUwCVpL7?Y4Dt(1d)ugvN#3+@W)1fj;3&jqptK^<~fkvN?bl S1TFC*m3=A8#cc=G(Fr#*AIFfDk(&1ouJ^K=~K|6gX)vOd%}iQ$GI&;Y*F e2+uTMUj{88n*)eJ;8O5p5asFW=d#Wzp$PzERVXO{ literal 0 HcmV?d00001 diff --git a/resources/colormaps/viridis.png b/resources/colormaps/viridis.png new file mode 100644 index 0000000000000000000000000000000000000000..2ac3d4bb69c5d416b943cc63f97b3a9b2a69fcb9 GIT binary patch literal 269 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K57&+L0q+w)1Igr}r>EaktF{gFnX~AX#9@g(C z*Dh`O65lnoIW^LZk?+iJ-8RPBFQq9bTta;m6pbe+gsymVds^kMX6@PD2|2fKUVS5^ zQByWqHS&CnxHmTC2`9;o!+ z-}UWd<@L0e-*aSkzPNGddiU~m@kOU?wuSALN&dF^wZy_#C-r0h95b3{`b}=PyZm?7 z+bj02|9t8Eca?~YrnW=e&J#s%9^(Jb9QdM>Yw=P;BcLz%QX@Rme0>?TfNTyR27yb# PlR=cHtDnm{r-UW|79Mfx literal 0 HcmV?d00001 diff --git a/testing/baselines/TestColorMap16bits.png b/testing/baselines/TestColorMap16bits.png new file mode 100644 index 0000000000..04645b3ed6 --- /dev/null +++ b/testing/baselines/TestColorMap16bits.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3c2b69a2a46dc0ca2aae92f6362529ae8b49d5db5ae73abed94fce9e6f1f3c89 +size 25177 diff --git a/testing/baselines/TestColorMap32bits.png b/testing/baselines/TestColorMap32bits.png new file mode 100644 index 0000000000..5d5e345d18 --- /dev/null +++ b/testing/baselines/TestColorMap32bits.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:75d4de9b2e9a8305a14bef645c0d1e75685b6ee307250ea94161a1a607652b03 +size 25953 diff --git a/testing/baselines/TestColorMapFile.png b/testing/baselines/TestColorMapFile.png new file mode 100644 index 0000000000..34895ab7ec --- /dev/null +++ b/testing/baselines/TestColorMapFile.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eaa6310ac92da85b69576bea3365d3414d9a4f35aaa217627b4b285b4696b73b +size 25928 diff --git a/testing/baselines/TestColorMapFileFullPath.png b/testing/baselines/TestColorMapFileFullPath.png new file mode 100644 index 0000000000..04645b3ed6 --- /dev/null +++ b/testing/baselines/TestColorMapFileFullPath.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3c2b69a2a46dc0ca2aae92f6362529ae8b49d5db5ae73abed94fce9e6f1f3c89 +size 25177 diff --git a/testing/baselines/TestColorMapStem.png b/testing/baselines/TestColorMapStem.png new file mode 100644 index 0000000000..34895ab7ec --- /dev/null +++ b/testing/baselines/TestColorMapStem.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eaa6310ac92da85b69576bea3365d3414d9a4f35aaa217627b4b285b4696b73b +size 25928 diff --git a/testing/data/viridis16.png b/testing/data/viridis16.png new file mode 100644 index 0000000000..026a076b58 --- /dev/null +++ b/testing/data/viridis16.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a417c77fbd61efec912c4e3e2dbd3c781ab8c932ef883286a3fd7b4f1780e091 +size 4404 diff --git a/testing/data/viridis32.hdr b/testing/data/viridis32.hdr new file mode 100644 index 0000000000..1440facfca --- /dev/null +++ b/testing/data/viridis32.hdr @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d613b9cc534e086dd3094d4d061b9132cddd5d049f98c463dd8a519dd27f694a +size 711 diff --git a/testing/data/viridis8.png b/testing/data/viridis8.png new file mode 100644 index 0000000000..f507a03a79 --- /dev/null +++ b/testing/data/viridis8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e9a19eb002d9c3ba13e6622bdcc6085621a6560bfec0ca54ac3e425d10cfd042 +size 236 diff --git a/testing/data/white_grayscale.png b/testing/data/white_grayscale.png new file mode 100644 index 0000000000..138b77bc1c --- /dev/null +++ b/testing/data/white_grayscale.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:296d5bb9ffaa8cc963d7542fc2fe91de6c1b9054bd87341d7cca0a975d7259cc +size 506 From 776874ebcb41131c38b8e1db811dbd8d49add50c Mon Sep 17 00:00:00 2001 From: Michael Migliore Date: Fri, 22 Mar 2024 15:57:31 +0100 Subject: [PATCH 2/8] review --- application/F3DColorMapTools.cxx | 11 +++++++++-- doc/user/COLOR_MAPS.md | 26 +++++++++++++++++++++++--- resources/colormaps/licenses.md | 6 +++--- 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/application/F3DColorMapTools.cxx b/application/F3DColorMapTools.cxx index 34194db973..08a40cf9ff 100644 --- a/application/F3DColorMapTools.cxx +++ b/application/F3DColorMapTools.cxx @@ -39,10 +39,17 @@ std::string Find(const std::string& str) for (const fs::path& dir : dirsToCheck) { - // If the string is a stem, add extension + // If the string is a stem, try adding supported extensions if (fs::path(str).stem() == str) { - cmPath = dir / (str + ".png"); + for (const std::string& ext : f3d::image::getSupportedFormats()) + { + cmPath = dir / (str + ext); + if (fs::exists(cmPath)) + { + return cmPath.string(); + } + } } else { diff --git a/doc/user/COLOR_MAPS.md b/doc/user/COLOR_MAPS.md index 4d2b65e980..e237a9940f 100644 --- a/doc/user/COLOR_MAPS.md +++ b/doc/user/COLOR_MAPS.md @@ -3,11 +3,13 @@ ## Image files It is possible to specify a color map using the `--colormap-file` option. -The value of the option can be a full path to an image file, a filename only is which case, these directories are used to find the file (in this order): +The value of the option can be a path to an image file, a filename or a filestem. +If it is not a path, these directories are used to find the file (in this order): * Linux: `${XDG_CONFIG_HOME}/f3d/colormaps`, `~/.config/f3d/colormaps`, `/etc/f3d/colormaps`, `/usr/share/f3d/colormaps`, `[install_dir]/share/f3d/colormaps` * Windows: `%APPDATA%\f3d\colormaps`, `[install_dir]\share\f3d\configs\colormaps` * macOS: `${XDG_CONFIG_HOME}/f3d/colormaps`, `~/.config/f3d/colormaps`, `/usr/local/etc/f3d/colormaps`, `f3d.app/Contents/Resources/configs/colormaps` -In case the filename omits the extension, PNG files only are searched. +The first existing file found is used. +If it is a filestem, all [supported image](#supported-formats) extensions are tried. We provide some ready to use color maps files, listed in the table below: @@ -23,10 +25,28 @@ plasma| viridis| -It is possible to create a custom color map by creating a simple RGB image in any supported format (PNG recommended), and any resolution (if the height is more than 1 row, only the first one is taken into account). The image must be copied in the user config directory: +It is possible to create a custom color map by creating a simple RGB image in any [supported formats](#supported-formats), and any resolution (if the height is more than 1 row, only the first one is taken into account). The image must be copied in the user config directory: * Linux/macOS: `~/.config/f3d/colormaps` * Windows: `%APPDATA%\f3d\colormaps` +### Supported formats + +Here's the list of all supported image formats that can be used as color maps: + +- `.png` +- `.pnm`, `.pgm`, `.ppm` +- `.tif`, `.tiff` +- `.bmp` +- `.slc` +- `.hdr` +- `.pic` +- `.jpeg`, `.jpg` +- `.MR` +- `.CT` +- `.mhd`, `.mha` +- `.tga` +- `.exr` (if `F3D_MODULE_EXR` is [enabled](../dev/BUILD.md)) + ## Custom values It is also possible to set values manually using `--colormap` option. A list of numbers between 0 and 1 must be specified. The size of the list is a multiple of 4 and each 4-components tuple correspond to the scalar value, followed by the RGB color. diff --git a/resources/colormaps/licenses.md b/resources/colormaps/licenses.md index d3412b5786..e5b76f9aca 100644 --- a/resources/colormaps/licenses.md +++ b/resources/colormaps/licenses.md @@ -1,11 +1,11 @@ |Name |Author |License | |----------|----------------------------------------------------|------------| |cividis |Jamie Nunez |BSD-3-Clause| -|cubehelix | |BSD-2-Clause| +|cubehelix |Dave Green |BSD-2-Clause| |gist_earth|David Munro |BSD-3-Clause| -|hot | |PSF | +|hot | |PSF | |inferno |Nathaniel J. Smith, Stefan van der Walt |CC0 | |magma |Nathaniel J. Smith, Stefan van der Walt |CC0 | |plasma |Nathaniel J. Smith, Stefan van der Walt |CC0 | -|seismic | |PSF | +|seismic | |PSF | |viridis |Nathaniel J. Smith, Stefan van der Walt, Eric Firing|CC0 | From 9af1edd19a8adbaba82c59066a0af0a57af38568 Mon Sep 17 00:00:00 2001 From: Michael Migliore Date: Fri, 22 Mar 2024 20:43:41 +0100 Subject: [PATCH 3/8] ci --- .github/actions/generic-ci/action.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/actions/generic-ci/action.yml b/.github/actions/generic-ci/action.yml index b5552ac34a..767408f03a 100644 --- a/.github/actions/generic-ci/action.yml +++ b/.github/actions/generic-ci/action.yml @@ -232,6 +232,7 @@ runs: run: | cmake --install . --component sdk cmake --install . --component configuration + cmake --install . --component colormaps - name: Build and configure python externally if: | From a2be94ee321e242911600f172accb4e9f7a90c14 Mon Sep 17 00:00:00 2001 From: Michael Migliore Date: Fri, 22 Mar 2024 20:53:00 +0100 Subject: [PATCH 4/8] remove catch --- application/F3DColorMapTools.cxx | 50 ++++++++++++-------------------- 1 file changed, 19 insertions(+), 31 deletions(-) diff --git a/application/F3DColorMapTools.cxx b/application/F3DColorMapTools.cxx index 08a40cf9ff..76b506c93a 100644 --- a/application/F3DColorMapTools.cxx +++ b/application/F3DColorMapTools.cxx @@ -23,52 +23,40 @@ std::string Find(const std::string& str) } } - fs::path cmPath; - try - { - std::vector dirsToCheck; - dirsToCheck.emplace_back(F3DConfigFileTools::GetUserConfigFileDirectory() / "colormaps"); + std::vector dirsToCheck; + dirsToCheck.emplace_back(F3DConfigFileTools::GetUserConfigFileDirectory() / "colormaps"); #ifdef __APPLE__ - dirsToCheck.emplace_back("/usr/local/etc/f3d/colormaps"); + dirsToCheck.emplace_back("/usr/local/etc/f3d/colormaps"); #endif #ifdef __linux__ - dirsToCheck.emplace_back("/etc/f3d/colormaps"); - dirsToCheck.emplace_back("/usr/share/f3d/colormaps"); + dirsToCheck.emplace_back("/etc/f3d/colormaps"); + dirsToCheck.emplace_back("/usr/share/f3d/colormaps"); #endif - dirsToCheck.emplace_back(F3DConfigFileTools::GetBinaryConfigFileDirectory() / "colormaps"); + dirsToCheck.emplace_back(F3DConfigFileTools::GetBinaryConfigFileDirectory() / "colormaps"); - for (const fs::path& dir : dirsToCheck) + for (const fs::path& dir : dirsToCheck) + { + // If the string is a stem, try adding supported extensions + if (fs::path(str).stem() == str) { - // If the string is a stem, try adding supported extensions - if (fs::path(str).stem() == str) + for (const std::string& ext : f3d::image::getSupportedFormats()) { - for (const std::string& ext : f3d::image::getSupportedFormats()) + fs::path cmPath = dir / (str + ext); + if (fs::exists(cmPath)) { - cmPath = dir / (str + ext); - if (fs::exists(cmPath)) - { - return cmPath.string(); - } + return cmPath.string(); } } - else - { - // If not, use directly - cmPath = dir / str; - } - + } + else + { + // If not, use directly + fs::path cmPath = dir / str; if (fs::exists(cmPath)) { return cmPath.string(); } } - - return {}; - } - catch (const fs::filesystem_error&) - { - f3d::log::error("Error recovering color map file path: ", str); - return {}; } return {}; From a7454e65179208b48dd7cdb6e545e5201dd23bbb Mon Sep 17 00:00:00 2001 From: Michael Migliore Date: Sat, 23 Mar 2024 22:01:36 +0100 Subject: [PATCH 5/8] review --- .github/actions/generic-ci/action.yml | 2 +- .github/baselines/install_output.png | 4 ++-- application/F3DColorMapTools.cxx | 2 +- application/F3DConfigFileTools.cxx | 4 ++-- application/F3DConfigFileTools.h | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/actions/generic-ci/action.yml b/.github/actions/generic-ci/action.yml index 767408f03a..ef6d46f875 100644 --- a/.github/actions/generic-ci/action.yml +++ b/.github/actions/generic-ci/action.yml @@ -347,7 +347,7 @@ runs: shell: bash working-directory: ${{github.workspace}}/install run: | - ${{ env.F3D_BIN_PATH }} ../source/testing/data/suzanne.obj --output=output/install_output.png --ref=../source/.github/baselines/install_output.png --resolution=300,300 --verbose + ${{ env.F3D_BIN_PATH }} ../source/testing/data/dragon.vtu --output=output/install_output.png --ref=../source/.github/baselines/install_output.png --resolution=300,300 --colormap-file=viridis --comp=0 --verbose - name: Check Install plugins if: | diff --git a/.github/baselines/install_output.png b/.github/baselines/install_output.png index ce0abee10c..84be24e3b5 100644 --- a/.github/baselines/install_output.png +++ b/.github/baselines/install_output.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b919965c4ff43dea4f5e21d87a0498bd7f5eb798cd4208aae9d4797504963997 -size 57459 +oid sha256:5db4d1d5cfa097e3b8ffbe41438d53df9369de13d9366fb218ccee81117a8886 +size 61913 diff --git a/application/F3DColorMapTools.cxx b/application/F3DColorMapTools.cxx index 76b506c93a..0533f3246b 100644 --- a/application/F3DColorMapTools.cxx +++ b/application/F3DColorMapTools.cxx @@ -32,7 +32,7 @@ std::string Find(const std::string& str) dirsToCheck.emplace_back("/etc/f3d/colormaps"); dirsToCheck.emplace_back("/usr/share/f3d/colormaps"); #endif - dirsToCheck.emplace_back(F3DConfigFileTools::GetBinaryConfigFileDirectory() / "colormaps"); + dirsToCheck.emplace_back(F3DConfigFileTools::GetBinaryResourceDirectory() / "colormaps"); for (const fs::path& dir : dirsToCheck) { diff --git a/application/F3DConfigFileTools.cxx b/application/F3DConfigFileTools.cxx index 00e6740b6f..3e5d0e9518 100644 --- a/application/F3DConfigFileTools.cxx +++ b/application/F3DConfigFileTools.cxx @@ -46,7 +46,7 @@ fs::path F3DConfigFileTools::GetUserConfigFileDirectory() } //---------------------------------------------------------------------------- -fs::path F3DConfigFileTools::GetBinaryConfigFileDirectory() +fs::path F3DConfigFileTools::GetBinaryResourceDirectory() { fs::path dirPath; try @@ -88,7 +88,7 @@ fs::path F3DConfigFileTools::GetConfigPath(const std::string& configSearch) dirsToCheck.emplace_back("/etc/f3d"); dirsToCheck.emplace_back("/usr/share/f3d/configs"); #endif - dirsToCheck.emplace_back(F3DConfigFileTools::GetBinaryConfigFileDirectory() / "configs"); + dirsToCheck.emplace_back(F3DConfigFileTools::GetBinaryResourceDirectory() / "configs"); for (const fs::path& dir : dirsToCheck) { diff --git a/application/F3DConfigFileTools.h b/application/F3DConfigFileTools.h index 60c5a766eb..65ad2162c2 100644 --- a/application/F3DConfigFileTools.h +++ b/application/F3DConfigFileTools.h @@ -13,7 +13,7 @@ namespace F3DConfigFileTools { std::filesystem::path GetUserConfigFileDirectory(); -std::filesystem::path GetBinaryConfigFileDirectory(); +std::filesystem::path GetBinaryResourceDirectory(); std::filesystem::path GetConfigPath(const std::string& configSearch); } From 9742311c5b26e323964fa0a9c49646b11fdadb3e Mon Sep 17 00:00:00 2001 From: Michael Migliore Date: Sun, 24 Mar 2024 21:39:12 +0100 Subject: [PATCH 6/8] fix install path --- application/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/CMakeLists.txt b/application/CMakeLists.txt index fa1660b1f1..301fa75a8c 100644 --- a/application/CMakeLists.txt +++ b/application/CMakeLists.txt @@ -213,7 +213,7 @@ install( # Default color maps install( DIRECTORY "${F3D_SOURCE_DIR}/resources/colormaps/" - DESTINATION "${f3d_config_dir}/colormaps" + DESTINATION "${f3d_resources_dir}/colormaps" COMPONENT colormaps EXCLUDE_FROM_ALL) From 7c3e76a35c478e13341bf2aa1139668d25f788d1 Mon Sep 17 00:00:00 2001 From: Michael Migliore Date: Mon, 25 Mar 2024 21:11:57 +0100 Subject: [PATCH 7/8] fix doc --- doc/user/COLOR_MAPS.md | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/doc/user/COLOR_MAPS.md b/doc/user/COLOR_MAPS.md index e237a9940f..c820f1a9f8 100644 --- a/doc/user/COLOR_MAPS.md +++ b/doc/user/COLOR_MAPS.md @@ -15,15 +15,15 @@ We provide some ready to use color maps files, listed in the table below: Name|Image ------|------ -cividis| -cubehelix| -gist_earth| -hot| -inferno| -magma| -plasma| -seismic| -viridis| +cividis| +cubehelix| +gist_earth| +hot| +inferno| +magma| +plasma| +seismic| +viridis| It is possible to create a custom color map by creating a simple RGB image in any [supported formats](#supported-formats), and any resolution (if the height is more than 1 row, only the first one is taken into account). The image must be copied in the user config directory: * Linux/macOS: `~/.config/f3d/colormaps` @@ -49,8 +49,9 @@ Here's the list of all supported image formats that can be used as color maps: ## Custom values -It is also possible to set values manually using `--colormap` option. A list of numbers between 0 and 1 must be specified. The size of the list is a multiple of 4 and each 4-components tuple correspond to the scalar value, followed by the RGB color. -For example, the default value corresponds to the `hot` preset which can be defined manually with `--colormap=0.0,0.0,0.0,0.0,0.4,0.9,0.0,0.0,0.8,0.9,0.9,0.0,1.0,1.0,1.0,1.0` which consists of 4 tuples: +If no colormap file is specified, it is also possible to set values manually using the `--colormap` option. A list of numbers between 0 and 1 must be specified. The size of the list is a multiple of 4 and each 4-components tuple correspond to the scalar value, followed by the RGB color. +For example, the default value corresponds to the `hot` preset which can be defined manually with `--colormap=0.0,0.0,0.0,0.0,0.4,0.9,0.0,0.0,0.8,0.9,0.9,0.0,1.0,1.0,1.0,1.0`. +It consists of 4 tuples: Value|RGB ------|------ 0.0| 0.0, 0.0, 0.0 From f1781a82a3777596817ab7598bf962380368c616 Mon Sep 17 00:00:00 2001 From: Michael Migliore Date: Thu, 28 Mar 2024 15:15:57 +0100 Subject: [PATCH 8/8] review --- application/F3DOptionsParser.cxx | 4 ++-- application/F3DStarter.cxx | 9 +++------ doc/user/OPTIONS.md | 2 +- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/application/F3DOptionsParser.cxx b/application/F3DOptionsParser.cxx index 6e3cf7dfa0..302d05a452 100644 --- a/application/F3DOptionsParser.cxx +++ b/application/F3DOptionsParser.cxx @@ -380,8 +380,8 @@ void ConfigurationOptions::GetOptions(F3DAppOptions& appOptions, f3d::options& o this->DeclareOption(grp4, "cells", "c", "Use a scalar array from the cells", options.getAsBoolRef("model.scivis.cells"), HasDefault::YES, MayHaveConfig::YES); this->DeclareOption(grp4, "range", "", "Custom range for the coloring by array", options.getAsDoubleVectorRef("model.scivis.range"), HasDefault::YES, MayHaveConfig::YES, ""); this->DeclareOption(grp4, "bar", "b", "Show scalar bar", options.getAsBoolRef("ui.bar"), HasDefault::YES, MayHaveConfig::YES); - this->DeclareOption(grp4, "colormap-file", "", "Specify a colormap image (ignored if \"colormap\" is specified)", appOptions.ColorMapFile, LocalHasDefaultNo, MayHaveConfig::YES, ""); - this->DeclareOption(grp4, "colormap", "", "Specify a custom colormap", options.getAsDoubleVectorRef("model.scivis.colormap"), HasDefault::YES, MayHaveConfig::YES, ""); + this->DeclareOption(grp4, "colormap-file", "", "Specify a colormap image", appOptions.ColorMapFile, LocalHasDefaultNo, MayHaveConfig::YES, ""); + this->DeclareOption(grp4, "colormap", "", "Specify a custom colormap (ignored if \"colormap-file\" is specified)", options.getAsDoubleVectorRef("model.scivis.colormap"), HasDefault::YES, MayHaveConfig::YES, ""); this->DeclareOption(grp4, "volume", "v", "Show volume if the file is compatible", options.getAsBoolRef("model.volume.enable"), HasDefault::YES, MayHaveConfig::YES); this->DeclareOption(grp4, "inverse", "i", "Inverse opacity function for volume rendering", options.getAsBoolRef("model.volume.inverse"), HasDefault::YES, MayHaveConfig::YES); diff --git a/application/F3DStarter.cxx b/application/F3DStarter.cxx index 5d01980954..56e311fa8c 100644 --- a/application/F3DStarter.cxx +++ b/application/F3DStarter.cxx @@ -348,16 +348,13 @@ int F3DStarter::Start(int argc, char** argv) if (!fullPath.empty()) { - auto cm = F3DColorMapTools::Read(fullPath); - - if (!cm.empty()) - { - this->Internals->Engine->getOptions().set("model.scivis.colormap", cm); - } + this->Internals->Engine->getOptions().set( + "model.scivis.colormap", F3DColorMapTools::Read(fullPath)); } else { f3d::log::error("Cannot find the colormap ", this->Internals->AppOptions.ColorMapFile); + this->Internals->Engine->getOptions().set("model.scivis.colormap", std::vector{}); } } diff --git a/doc/user/OPTIONS.md b/doc/user/OPTIONS.md index 1f04904113..6515d0a4fb 100644 --- a/doc/user/OPTIONS.md +++ b/doc/user/OPTIONS.md @@ -85,7 +85,7 @@ Options|Default|Description \-\-range=\||Set a *custom range for the coloring* by the array.
Use with the scalar option. -b, \-\-bar||Show *scalar bar* of the coloring by array.
Use with the scalar option. \-\-colormap\-file=\||Set a *colormap file for the coloring*.
See [color maps](COLOR_MAPS.md).
Use with the scalar option. -\-\-colormap=\||Set a *custom colormap for the coloring*.
This is a list of colors in the format `val1,red1,green1,blue1,...,valN,redN,greenN,blueN`
where all values are in the range (0,1).
Use with the scalar option. +\-\-colormap=\||Set a *custom colormap for the coloring*.
This is a list of colors in the format `val1,red1,green1,blue1,...,valN,redN,greenN,blueN`
where all values are in the range (0,1).
Ignored if `--colormap-file` option is specified.
Use with the scalar option. -v, \-\-volume||Enable *volume rendering*. It is only available for 3D image data (vti, dcm, nrrd, mhd files) and will display nothing with other formats. -i, \-\-inverse||Inverse the linear opacity function used for volume rendering.