mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 10:10:05 +00:00 
			
		
		
		
	Color table implementation
This commit is contained in:
		
							parent
							
								
									6c25ce4230
								
							
						
					
					
						commit
						d734bc6a0a
					
				
					 12 changed files with 437 additions and 5 deletions
				
			
		
							
								
								
									
										3
									
								
								.gitmodules
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitmodules
									
										
									
									
										vendored
									
									
								
							|  | @ -7,3 +7,6 @@ | ||||||
| [submodule "test/data"] | [submodule "test/data"] | ||||||
| 	path = test/data | 	path = test/data | ||||||
| 	url = ../supercell-wx-test-data | 	url = ../supercell-wx-test-data | ||||||
|  | [submodule "external/hsluv-c"] | ||||||
|  | 	path = external/hsluv-c | ||||||
|  | 	url = https://github.com/hsluv/hsluv-c.git | ||||||
|  |  | ||||||
							
								
								
									
										7
									
								
								external/CMakeLists.txt
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								external/CMakeLists.txt
									
										
									
									
										vendored
									
									
								
							|  | @ -1,4 +1,11 @@ | ||||||
| cmake_minimum_required(VERSION 3.11) | cmake_minimum_required(VERSION 3.11) | ||||||
| set(PROJECT_NAME scwx-external) | set(PROJECT_NAME scwx-external) | ||||||
| 
 | 
 | ||||||
|  | set_property(DIRECTORY | ||||||
|  |              APPEND | ||||||
|  |              PROPERTY CMAKE_CONFIGURE_DEPENDS | ||||||
|  |              hsluv-c.cmake | ||||||
|  |              mapbox-gl-native.cmake) | ||||||
|  | 
 | ||||||
|  | include(hsluv-c.cmake) | ||||||
| include(mapbox-gl-native.cmake) | include(mapbox-gl-native.cmake) | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								external/hsluv-c
									
										
									
									
										vendored
									
									
										Submodule
									
								
							
							
						
						
									
										1
									
								
								external/hsluv-c
									
										
									
									
										vendored
									
									
										Submodule
									
								
							|  | @ -0,0 +1 @@ | ||||||
|  | Subproject commit 59539e04a6fa648935cbe57c2104041f23136c4a | ||||||
							
								
								
									
										9
									
								
								external/hsluv-c.cmake
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								external/hsluv-c.cmake
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | ||||||
|  | cmake_minimum_required(VERSION 3.11) | ||||||
|  | set(PROJECT_NAME scwx-hsluv-c) | ||||||
|  | 
 | ||||||
|  | set(HSLUV_C_TESTS OFF) | ||||||
|  | add_subdirectory(hsluv-c) | ||||||
|  | 
 | ||||||
|  | set(HSLUV_C_INCLUDE_DIR ${hsluv-c_SOURCE_DIR}/src PARENT_SCOPE) | ||||||
|  | 
 | ||||||
|  | set_target_properties(hsluv-c PROPERTIES FOLDER hsluv) | ||||||
|  | @ -1,2 +1,8 @@ | ||||||
| cmake_minimum_required(VERSION 3.11) | cmake_minimum_required(VERSION 3.11) | ||||||
|  | 
 | ||||||
|  | set_property(DIRECTORY | ||||||
|  |              APPEND | ||||||
|  |              PROPERTY CMAKE_CONFIGURE_DEPENDS | ||||||
|  |              test.cmake) | ||||||
|  | 
 | ||||||
| include(test.cmake) | include(test.cmake) | ||||||
|  |  | ||||||
|  | @ -1 +1 @@ | ||||||
| Subproject commit 40f68fe08977e5168679ce0419834312a6369205 | Subproject commit 4bc8b8283fcd9d3ed0bcb3099d36db269209b7df | ||||||
							
								
								
									
										34
									
								
								test/source/scwx/common/color_table.test.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								test/source/scwx/common/color_table.test.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,34 @@ | ||||||
|  | #include <scwx/common/color_table.hpp> | ||||||
|  | 
 | ||||||
|  | #include <gtest/gtest.h> | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace common | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | TEST(color_table, reflectivity) | ||||||
|  | { | ||||||
|  |    std::string filename(std::string(SCWX_TEST_DATA_DIR) + | ||||||
|  |                         "/colors/reflectivity.pal"); | ||||||
|  | 
 | ||||||
|  |    std::shared_ptr<ColorTable> ct = ColorTable::Load(filename); | ||||||
|  | 
 | ||||||
|  |    EXPECT_EQ(ct->Color(5), boost::gil::rgba8_pixel_t(164, 164, 255, 255)); | ||||||
|  |    EXPECT_EQ(ct->Color(10), boost::gil::rgba8_pixel_t(164, 164, 255, 255)); | ||||||
|  |    EXPECT_EQ(ct->Color(20), boost::gil::rgba8_pixel_t(64, 128, 255, 255)); | ||||||
|  |    EXPECT_EQ(ct->Color(30), boost::gil::rgba8_pixel_t(0, 255, 0, 255)); | ||||||
|  |    EXPECT_EQ(ct->Color(32), boost::gil::rgba8_pixel_t(0, 230, 0, 255)); | ||||||
|  |    EXPECT_EQ(ct->Color(35), boost::gil::rgba8_pixel_t(0, 192, 0, 255)); | ||||||
|  |    EXPECT_EQ(ct->Color(40), boost::gil::rgba8_pixel_t(255, 255, 0, 255)); | ||||||
|  |    EXPECT_EQ(ct->Color(50), boost::gil::rgba8_pixel_t(255, 0, 0, 255)); | ||||||
|  |    EXPECT_EQ(ct->Color(55), boost::gil::rgba8_pixel_t(208, 0, 0, 255)); | ||||||
|  |    EXPECT_EQ(ct->Color(60), boost::gil::rgba8_pixel_t(255, 0, 255, 255)); | ||||||
|  |    EXPECT_EQ(ct->Color(65), boost::gil::rgba8_pixel_t(192, 0, 192, 255)); | ||||||
|  |    EXPECT_EQ(ct->Color(70), boost::gil::rgba8_pixel_t(255, 255, 255, 255)); | ||||||
|  |    EXPECT_EQ(ct->Color(80), boost::gil::rgba8_pixel_t(128, 128, 128, 255)); | ||||||
|  |    EXPECT_EQ(ct->Color(85), boost::gil::rgba8_pixel_t(128, 128, 128, 255)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace common
 | ||||||
|  | } // namespace scwx
 | ||||||
|  | @ -8,15 +8,18 @@ find_package(BZip2) | ||||||
| find_package(GTest) | find_package(GTest) | ||||||
| 
 | 
 | ||||||
| set(SRC_MAIN source/scwx/wxtest.cpp) | set(SRC_MAIN source/scwx/wxtest.cpp) | ||||||
|  | set(SRC_COMMON_TESTS source/scwx/common/color_table.test.cpp) | ||||||
| set(SRC_UTIL_TESTS source/scwx/util/rangebuf.test.cpp | set(SRC_UTIL_TESTS source/scwx/util/rangebuf.test.cpp | ||||||
|                    source/scwx/util/vectorbuf.test.cpp) |                    source/scwx/util/vectorbuf.test.cpp) | ||||||
| set(SRC_WSR88D_TESTS source/scwx/wsr88d/ar2v_file.test.cpp) | set(SRC_WSR88D_TESTS source/scwx/wsr88d/ar2v_file.test.cpp) | ||||||
| 
 | 
 | ||||||
| add_executable(wxtest ${SRC_MAIN} | add_executable(wxtest ${SRC_MAIN} | ||||||
|  |                       ${SRC_COMMON_TESTS} | ||||||
|                       ${SRC_UTIL_TESTS} |                       ${SRC_UTIL_TESTS} | ||||||
|                       ${SRC_WSR88D_TESTS}) |                       ${SRC_WSR88D_TESTS}) | ||||||
| 
 | 
 | ||||||
| source_group("Source Files\\main"   FILES ${SRC_MAIN}) | source_group("Source Files\\main"   FILES ${SRC_MAIN}) | ||||||
|  | source_group("Source Files\\common" FILES ${SRC_COMMON_TESTS}) | ||||||
| source_group("Source Files\\util"   FILES ${SRC_UTIL_TESTS}) | source_group("Source Files\\util"   FILES ${SRC_UTIL_TESTS}) | ||||||
| source_group("Source Files\\wsr88d" FILES ${SRC_WSR88D_TESTS}) | source_group("Source Files\\wsr88d" FILES ${SRC_WSR88D_TESTS}) | ||||||
| 
 | 
 | ||||||
|  | @ -38,6 +41,7 @@ target_link_libraries(wxtest Boost::iostreams | ||||||
|                              Boost::log |                              Boost::log | ||||||
|                              BZip2::BZip2 |                              BZip2::BZip2 | ||||||
|                              GTest::gtest |                              GTest::gtest | ||||||
|  |                              hsluv-c | ||||||
|                              wxdata) |                              wxdata) | ||||||
| 
 | 
 | ||||||
| if (WIN32) | if (WIN32) | ||||||
|  |  | ||||||
							
								
								
									
										48
									
								
								wxdata/include/scwx/common/color_table.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								wxdata/include/scwx/common/color_table.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,48 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <memory> | ||||||
|  | #include <string> | ||||||
|  | #include <vector> | ||||||
|  | 
 | ||||||
|  | #include <boost/gil.hpp> | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace common | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | class ColorTableImpl; | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief Color Table | ||||||
|  |  * | ||||||
|  |  * Implementation based on: | ||||||
|  |  * Color Table File Specification | ||||||
|  |  * Mike Gibson | ||||||
|  |  * Gibson Ridge Software, LLC.  Used with permission. | ||||||
|  |  * http://www.grlevelx.com/manuals/color_tables/files_color_table.htm
 | ||||||
|  |  */ | ||||||
|  | class ColorTable | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |    explicit ColorTable(); | ||||||
|  |    ~ColorTable(); | ||||||
|  | 
 | ||||||
|  |    ColorTable(const ColorTable&) = delete; | ||||||
|  |    ColorTable& operator=(const ColorTable&) = delete; | ||||||
|  | 
 | ||||||
|  |    ColorTable(ColorTable&&) noexcept; | ||||||
|  |    ColorTable& operator=(ColorTable&&) noexcept; | ||||||
|  | 
 | ||||||
|  |    boost::gil::rgba8_pixel_t Color(float value) const; | ||||||
|  | 
 | ||||||
|  |    static std::shared_ptr<ColorTable> Load(const std::string& filename); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |    std::unique_ptr<ColorTableImpl> p; | ||||||
|  | 
 | ||||||
|  |    void ProcessLine(const std::vector<std::string>& tokenList); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace common
 | ||||||
|  | } // namespace scwx
 | ||||||
							
								
								
									
										313
									
								
								wxdata/source/scwx/common/color_table.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										313
									
								
								wxdata/source/scwx/common/color_table.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,313 @@ | ||||||
|  | #include <scwx/common/color_table.hpp> | ||||||
|  | 
 | ||||||
|  | #include <cmath> | ||||||
|  | #include <fstream> | ||||||
|  | #include <limits> | ||||||
|  | #include <map> | ||||||
|  | #include <optional> | ||||||
|  | #include <sstream> | ||||||
|  | 
 | ||||||
|  | #include <boost/gil.hpp> | ||||||
|  | #include <boost/log/trivial.hpp> | ||||||
|  | 
 | ||||||
|  | #include <hsluv.h> | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace common | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | static const std::string logPrefix_ {"[scwx::common::color_table] "}; | ||||||
|  | 
 | ||||||
|  | enum class ColorMode | ||||||
|  | { | ||||||
|  |    RGBA, | ||||||
|  |    HSLuv | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static boost::gil::rgba8_pixel_t | ||||||
|  | ParseColor(const std::vector<std::string>& tokenList, | ||||||
|  |            size_t                          startIndex, | ||||||
|  |            ColorMode                       colorMode, | ||||||
|  |            bool                            hasAlpha = true); | ||||||
|  | template<typename T> | ||||||
|  | T RoundChannel(double value); | ||||||
|  | template<typename T> | ||||||
|  | T StringToDecimal(const std::string& str); | ||||||
|  | 
 | ||||||
|  | class ColorTableImpl | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |    explicit ColorTableImpl() : | ||||||
|  |        product_ {}, | ||||||
|  |        units_ {}, | ||||||
|  |        scale_ {1.0f}, | ||||||
|  |        offset_ {0.0f}, | ||||||
|  |        step_ {10}, | ||||||
|  |        rfColor_ {0, 0, 0, 0}, | ||||||
|  |        colorMode_ {ColorMode::RGBA}, | ||||||
|  |        colorMap_ {} {}; | ||||||
|  |    ~ColorTableImpl() = default; | ||||||
|  | 
 | ||||||
|  |    std::string               product_; | ||||||
|  |    std::string               units_; | ||||||
|  |    float                     scale_; | ||||||
|  |    float                     offset_; | ||||||
|  |    long                      step_; | ||||||
|  |    boost::gil::rgba8_pixel_t rfColor_; | ||||||
|  |    ColorMode                 colorMode_; | ||||||
|  | 
 | ||||||
|  |    std::map<float, | ||||||
|  |             std::pair<boost::gil::rgba8_pixel_t, | ||||||
|  |                       std::optional<boost::gil::rgba8_pixel_t>>> | ||||||
|  |       colorMap_; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | ColorTable::ColorTable() : p(std::make_unique<ColorTableImpl>()) {} | ||||||
|  | ColorTable::~ColorTable() = default; | ||||||
|  | 
 | ||||||
|  | ColorTable::ColorTable(ColorTable&&) noexcept = default; | ||||||
|  | ColorTable& ColorTable::operator=(ColorTable&&) noexcept = default; | ||||||
|  | 
 | ||||||
|  | boost::gil::rgba8_pixel_t ColorTable::Color(float value) const | ||||||
|  | { | ||||||
|  |    boost::gil::rgba8_pixel_t color; | ||||||
|  |    bool                      found = false; | ||||||
|  | 
 | ||||||
|  |    value = value * p->scale_ + p->offset_; | ||||||
|  | 
 | ||||||
|  |    auto prev = p->colorMap_.cbegin(); | ||||||
|  |    for (auto it = p->colorMap_.cbegin(); it != p->colorMap_.cend(); ++it) | ||||||
|  |    { | ||||||
|  |       if (value < it->first) | ||||||
|  |       { | ||||||
|  |          if (it == p->colorMap_.cbegin()) | ||||||
|  |          { | ||||||
|  |             color = it->second.first; | ||||||
|  |          } | ||||||
|  |          else | ||||||
|  |          { | ||||||
|  |             // Interpolate
 | ||||||
|  |             float key1 = prev->first; | ||||||
|  |             float key2 = it->first; | ||||||
|  | 
 | ||||||
|  |             boost::gil::rgba8_pixel_t color1 = prev->second.first; | ||||||
|  |             boost::gil::rgba8_pixel_t color2 = (prev->second.second) ? | ||||||
|  |                                                   prev->second.second.value() : | ||||||
|  |                                                   it->second.first; | ||||||
|  | 
 | ||||||
|  |             float t = (value - key1) / (key2 - key1); | ||||||
|  |             color[0] = | ||||||
|  |                RoundChannel<uint8_t>(std::lerp(color1[0], color2[0], t)); | ||||||
|  |             color[1] = | ||||||
|  |                RoundChannel<uint8_t>(std::lerp(color1[1], color2[1], t)); | ||||||
|  |             color[2] = | ||||||
|  |                RoundChannel<uint8_t>(std::lerp(color1[2], color2[2], t)); | ||||||
|  |             color[3] = | ||||||
|  |                RoundChannel<uint8_t>(std::lerp(color1[3], color2[3], t)); | ||||||
|  |          } | ||||||
|  | 
 | ||||||
|  |          found = true; | ||||||
|  |          break; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       prev = it; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    if (!found) | ||||||
|  |    { | ||||||
|  |       color = prev->second.first; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    return color; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::shared_ptr<ColorTable> ColorTable::Load(const std::string& filename) | ||||||
|  | { | ||||||
|  |    BOOST_LOG_TRIVIAL(debug) | ||||||
|  |       << logPrefix_ << "Loading color table: " << filename; | ||||||
|  | 
 | ||||||
|  |    std::shared_ptr<ColorTable> p = std::make_shared<ColorTable>(); | ||||||
|  | 
 | ||||||
|  |    std::ifstream f(filename, std::ios_base::in); | ||||||
|  | 
 | ||||||
|  |    std::string line; | ||||||
|  |    while (std::getline(f, line)) | ||||||
|  |    { | ||||||
|  |       std::string              token; | ||||||
|  |       std::istringstream       tokens(line); | ||||||
|  |       std::vector<std::string> tokenList; | ||||||
|  | 
 | ||||||
|  |       while (tokens >> token) | ||||||
|  |       { | ||||||
|  |          if (token.find(';') != std::string::npos) | ||||||
|  |          { | ||||||
|  |             break; | ||||||
|  |          } | ||||||
|  | 
 | ||||||
|  |          tokenList.push_back(std::move(token)); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if (tokenList.size() >= 2) | ||||||
|  |       { | ||||||
|  |          try | ||||||
|  |          { | ||||||
|  |             p->ProcessLine(tokenList); | ||||||
|  |          } | ||||||
|  |          catch (const std::exception&) | ||||||
|  |          { | ||||||
|  |             BOOST_LOG_TRIVIAL(warning) | ||||||
|  |                << logPrefix_ << "Could not parse line: " << line; | ||||||
|  |          } | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    return p; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ColorTable::ProcessLine(const std::vector<std::string>& tokenList) | ||||||
|  | { | ||||||
|  |    if (tokenList[0] == "Product:") | ||||||
|  |    { | ||||||
|  |       // Product: string
 | ||||||
|  |       p->product_ = tokenList[1]; | ||||||
|  |    } | ||||||
|  |    else if (tokenList[0] == "Units:") | ||||||
|  |    { | ||||||
|  |       // Units: string
 | ||||||
|  |       p->units_ = tokenList[1]; | ||||||
|  |    } | ||||||
|  |    else if (tokenList[0] == "Scale:") | ||||||
|  |    { | ||||||
|  |       // Scale: float
 | ||||||
|  |       p->scale_ = std::stof(tokenList[1]); | ||||||
|  |    } | ||||||
|  |    else if (tokenList[0] == "Offset:") | ||||||
|  |    { | ||||||
|  |       // Offset: float
 | ||||||
|  |       p->offset_ = std::stof(tokenList[1]); | ||||||
|  |    } | ||||||
|  |    else if (tokenList[0] == "Step:") | ||||||
|  |    { | ||||||
|  |       // Step: float
 | ||||||
|  |       p->step_ = std::stof(tokenList[1]); | ||||||
|  |    } | ||||||
|  |    else if (tokenList[0] == "RF") | ||||||
|  |    { | ||||||
|  |       // RF: R G B [A]
 | ||||||
|  |       p->rfColor_ = ParseColor(tokenList, 1, p->colorMode_); | ||||||
|  |    } | ||||||
|  |    else if (tokenList[0] == "Color:") | ||||||
|  |    { | ||||||
|  |       // Color: value R G B [R G B]
 | ||||||
|  |       float key = std::stof(tokenList[1]); | ||||||
|  | 
 | ||||||
|  |       boost::gil::rgba8_pixel_t color1 = | ||||||
|  |          ParseColor(tokenList, 2, p->colorMode_, false); | ||||||
|  |       std::optional<boost::gil::rgba8_pixel_t> color2; | ||||||
|  | 
 | ||||||
|  |       if (tokenList.size() >= 8) | ||||||
|  |       { | ||||||
|  |          color2 = ParseColor(tokenList, 5, p->colorMode_, false); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       p->colorMap_[key] = std::make_pair(color1, color2); | ||||||
|  |    } | ||||||
|  |    else if (tokenList[0] == "Color4:") | ||||||
|  |    { | ||||||
|  |       // Color4: value R G B A [R G B A]
 | ||||||
|  |       float key = std::stof(tokenList[1]); | ||||||
|  | 
 | ||||||
|  |       boost::gil::rgba8_pixel_t color1 = | ||||||
|  |          ParseColor(tokenList, 2, p->colorMode_); | ||||||
|  |       std::optional<boost::gil::rgba8_pixel_t> color2; | ||||||
|  | 
 | ||||||
|  |       if (tokenList.size() >= 10) | ||||||
|  |       { | ||||||
|  |          color2 = ParseColor(tokenList, 6, p->colorMode_); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       p->colorMap_[key] = std::make_pair(color1, color2); | ||||||
|  |    } | ||||||
|  |    else if (tokenList[0] == "SolidColor:") | ||||||
|  |    { | ||||||
|  |       // SolidColor: value R G B
 | ||||||
|  |       float key = std::stof(tokenList[1]); | ||||||
|  | 
 | ||||||
|  |       boost::gil::rgba8_pixel_t color1 = | ||||||
|  |          ParseColor(tokenList, 2, p->colorMode_, false); | ||||||
|  | 
 | ||||||
|  |       p->colorMap_[key] = std::make_pair(color1, color1); | ||||||
|  |    } | ||||||
|  |    else if (tokenList[0] == "SolidColor4:") | ||||||
|  |    { | ||||||
|  |       // SolidColor4: value R G B A
 | ||||||
|  |       float key = std::stof(tokenList[1]); | ||||||
|  | 
 | ||||||
|  |       boost::gil::rgba8_pixel_t color1 = | ||||||
|  |          ParseColor(tokenList, 2, p->colorMode_); | ||||||
|  | 
 | ||||||
|  |       p->colorMap_[key] = std::make_pair(color1, color1); | ||||||
|  |    } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static boost::gil::rgba8_pixel_t | ||||||
|  | ParseColor(const std::vector<std::string>& tokenList, | ||||||
|  |            size_t                          startIndex, | ||||||
|  |            ColorMode                       colorMode, | ||||||
|  |            bool                            hasAlpha) | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  |    uint8_t r; | ||||||
|  |    uint8_t g; | ||||||
|  |    uint8_t b; | ||||||
|  |    uint8_t a = 255; | ||||||
|  | 
 | ||||||
|  |    if (colorMode == ColorMode::RGBA) | ||||||
|  |    { | ||||||
|  |       r = StringToDecimal<uint8_t>(tokenList[startIndex + 0]); | ||||||
|  |       g = StringToDecimal<uint8_t>(tokenList[startIndex + 1]); | ||||||
|  |       b = StringToDecimal<uint8_t>(tokenList[startIndex + 2]); | ||||||
|  | 
 | ||||||
|  |       if (hasAlpha && tokenList.size() >= startIndex + 4) | ||||||
|  |       { | ||||||
|  |          a = StringToDecimal<uint8_t>(tokenList[startIndex + 3]); | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  |    else // if (colorMode == ColorMode::HSLuv)
 | ||||||
|  |    { | ||||||
|  |       double h = std::stod(tokenList[startIndex + 0]); | ||||||
|  |       double s = std::stod(tokenList[startIndex + 1]); | ||||||
|  |       double l = std::stod(tokenList[startIndex + 2]); | ||||||
|  |       double dr; | ||||||
|  |       double dg; | ||||||
|  |       double db; | ||||||
|  | 
 | ||||||
|  |       hsluv2rgb(h, s, l, &dr, &dg, &db); | ||||||
|  | 
 | ||||||
|  |       r = RoundChannel<uint8_t>(dr * 255.0); | ||||||
|  |       g = RoundChannel<uint8_t>(dg * 255.0); | ||||||
|  |       b = RoundChannel<uint8_t>(db * 255.0); | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    return boost::gil::rgba8_pixel_t {r, g, b, a}; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template<typename T> | ||||||
|  | T RoundChannel(double value) | ||||||
|  | { | ||||||
|  |    return std::clamp<int>(std::lround(value), | ||||||
|  |                           std::numeric_limits<T>::min(), | ||||||
|  |                           std::numeric_limits<T>::max()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template<typename T> | ||||||
|  | T StringToDecimal(const std::string& str) | ||||||
|  | { | ||||||
|  |    return std::clamp<int>(std::stoi(str), | ||||||
|  |                           std::numeric_limits<T>::min(), | ||||||
|  |                           std::numeric_limits<T>::max()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace common
 | ||||||
|  | } // namespace scwx
 | ||||||
|  | @ -38,7 +38,7 @@ public: | ||||||
|    void HandleMessage(std::shared_ptr<rda::Message>& message); |    void HandleMessage(std::shared_ptr<rda::Message>& message); | ||||||
|    void LoadLDMRecords(std::ifstream& f); |    void LoadLDMRecords(std::ifstream& f); | ||||||
|    void ParseLDMRecords(); |    void ParseLDMRecords(); | ||||||
|    void ProcessRadarData(std::shared_ptr<rda::DigitalRadarData>& message); |    void ProcessRadarData(std::shared_ptr<rda::DigitalRadarData> message); | ||||||
|    void ProcessVcpData(); |    void ProcessVcpData(); | ||||||
| 
 | 
 | ||||||
|    std::string tapeFilename_; |    std::string tapeFilename_; | ||||||
|  | @ -245,7 +245,7 @@ void Ar2vFileImpl::HandleMessage(std::shared_ptr<rda::Message>& message) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Ar2vFileImpl::ProcessRadarData( | void Ar2vFileImpl::ProcessRadarData( | ||||||
|    std::shared_ptr<rda::DigitalRadarData>& message) |    std::shared_ptr<rda::DigitalRadarData> message) | ||||||
| { | { | ||||||
|    uint16_t azimuthIndex   = message->azimuth_number() - 1; |    uint16_t azimuthIndex   = message->azimuth_number() - 1; | ||||||
|    uint16_t elevationIndex = message->elevation_number() - 1; |    uint16_t elevationIndex = message->elevation_number() - 1; | ||||||
|  |  | ||||||
|  | @ -2,6 +2,8 @@ project(scwx-data) | ||||||
| 
 | 
 | ||||||
| find_package(Boost) | find_package(Boost) | ||||||
| 
 | 
 | ||||||
|  | set(HDR_COMMON include/scwx/common/color_table.hpp) | ||||||
|  | set(SRC_COMMON source/scwx/common/color_table.cpp) | ||||||
| set(HDR_UTIL include/scwx/util/rangebuf.hpp | set(HDR_UTIL include/scwx/util/rangebuf.hpp | ||||||
|              include/scwx/util/vectorbuf.hpp) |              include/scwx/util/vectorbuf.hpp) | ||||||
| set(SRC_UTIL source/scwx/util/rangebuf.cpp | set(SRC_UTIL source/scwx/util/rangebuf.cpp | ||||||
|  | @ -28,13 +30,17 @@ set(SRC_WSR88D_RDA source/scwx/wsr88d/rda/clutter_filter_map.cpp | ||||||
|                    source/scwx/wsr88d/rda/rda_status_data.cpp |                    source/scwx/wsr88d/rda/rda_status_data.cpp | ||||||
|                    source/scwx/wsr88d/rda/volume_coverage_pattern_data.cpp) |                    source/scwx/wsr88d/rda/volume_coverage_pattern_data.cpp) | ||||||
| 
 | 
 | ||||||
| add_library(wxdata OBJECT ${HDR_UTIL} | add_library(wxdata OBJECT ${HDR_COMMON} | ||||||
|  |                           ${SRC_COMMON} | ||||||
|  |                           ${HDR_UTIL} | ||||||
|                           ${SRC_UTIL} |                           ${SRC_UTIL} | ||||||
|                           ${HDR_WSR88D} |                           ${HDR_WSR88D} | ||||||
|                           ${SRC_WSR88D} |                           ${SRC_WSR88D} | ||||||
|                           ${HDR_WSR88D_RDA} |                           ${HDR_WSR88D_RDA} | ||||||
|                           ${SRC_WSR88D_RDA}) |                           ${SRC_WSR88D_RDA}) | ||||||
| 
 | 
 | ||||||
|  | source_group("Header Files\\common"      FILES ${HDR_COMMON}) | ||||||
|  | source_group("Source Files\\common"      FILES ${SRC_COMMON}) | ||||||
| source_group("Header Files\\util"        FILES ${HDR_UTIL}) | source_group("Header Files\\util"        FILES ${HDR_UTIL}) | ||||||
| source_group("Source Files\\util"        FILES ${SRC_UTIL}) | source_group("Source Files\\util"        FILES ${SRC_UTIL}) | ||||||
| source_group("Header Files\\wsr88d"      FILES ${HDR_WSR88D}) | source_group("Header Files\\wsr88d"      FILES ${HDR_WSR88D}) | ||||||
|  | @ -43,6 +49,7 @@ source_group("Header Files\\wsr88d\\rda" FILES ${HDR_WSR88D_RDA}) | ||||||
| source_group("Source Files\\wsr88d\\rda" FILES ${SRC_WSR88D_RDA}) | source_group("Source Files\\wsr88d\\rda" FILES ${SRC_WSR88D_RDA}) | ||||||
| 
 | 
 | ||||||
| target_include_directories(wxdata PRIVATE ${Boost_INCLUDE_DIR} | target_include_directories(wxdata PRIVATE ${Boost_INCLUDE_DIR} | ||||||
|  |                                           ${HSLUV_C_INCLUDE_DIR} | ||||||
|                                           ${scwx-data_SOURCE_DIR}/include |                                           ${scwx-data_SOURCE_DIR}/include | ||||||
|                                           ${scwx-data_SOURCE_DIR}/source) |                                           ${scwx-data_SOURCE_DIR}/source) | ||||||
| target_include_directories(wxdata INTERFACE ${scwx-data_SOURCE_DIR}/include) | target_include_directories(wxdata INTERFACE ${scwx-data_SOURCE_DIR}/include) | ||||||
|  | @ -51,6 +58,6 @@ if(MSVC) | ||||||
|     target_compile_options(wxdata PRIVATE /W3) |     target_compile_options(wxdata PRIVATE /W3) | ||||||
| endif() | endif() | ||||||
| 
 | 
 | ||||||
| set_target_properties(wxdata PROPERTIES CXX_STANDARD 17 | set_target_properties(wxdata PROPERTIES CXX_STANDARD 20 | ||||||
|                                         CXX_STANDARD_REQUIRED ON |                                         CXX_STANDARD_REQUIRED ON | ||||||
|                                         CXX_EXTENSIONS OFF) |                                         CXX_EXTENSIONS OFF) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat