cgv
Loading...
Searching...
No Matches
color_map_reader.h
1#pragma once
2
3#include <string>
4
5#include <cgv/base/import.h>
6#include <cgv/media/image/image_reader.h>
7#include <cgv/render/color_map.h>
8#include <cgv/utils/file.h>
9
10#include <tinyxml2/tinyxml2.h>
11#include <cgv_xml/query.h>
12
13namespace cgv {
14namespace app {
15
17public:
18 // configuration for xml tag and attribute name identifiers
20 std::string color_map_tag_id = "ColorMap";
21 std::string point_tag_id = "Point";
22 std::string color_point_tag_id = "ColorPoint";
23 std::string opacity_point_tag_id = "OpacityPoint";
24 std::string name_value_id = "name";
25 std::string position_value_id = "x";
26 std::string red_value_id = "r";
27 std::string green_value_id = "g";
28 std::string blue_value_id = "b";
29 std::string opactiy_value_id = "o";
30 bool color_value_type_float = true;
31 bool opacity_value_type_float = true;
32 bool apply_gamma = false;
33 };
34 static const identifier_config& default_identifier_config() {
35 static const identifier_config default_ic;
36 return default_ic;
37 }
38
39 // data structure of loaded color maps result
40 typedef std::vector<std::pair<std::string, cgv::render::color_map>> result;
41
42private:
43 struct point_info {
44 float x = -1.0f;
45 float o = -1.0f;
46 float r = -1.0f;
47 float g = -1.0f;
48 float b = -1.0f;
49 };
50
51 static void extract_value(const tinyxml2::XMLElement& elem, const std::string& name, bool as_float, float& value) {
52
53 if(as_float) {
54 elem.QueryFloatAttribute(name.c_str(), &value);
55 } else {
56 int temp;
57 if(elem.QueryIntAttribute(name.c_str(), &temp) == tinyxml2::XML_SUCCESS)
58 value = static_cast<float>(temp) / 255.0f;
59 }
60 }
61
62 static point_info extract_control_point(const tinyxml2::XMLElement& elem, const identifier_config& config) {
63
64 point_info pi;
65 extract_value(elem, config.position_value_id, true, pi.x);
66 extract_value(elem, config.opactiy_value_id, config.opacity_value_type_float, pi.o);
67 extract_value(elem, config.red_value_id, config.color_value_type_float, pi.r);
68 extract_value(elem, config.green_value_id, config.color_value_type_float, pi.g);
69 extract_value(elem, config.blue_value_id, config.color_value_type_float, pi.b);
70 return pi;
71 }
72
73 static void extract_color_map(const tinyxml2::XMLElement& elem, result& entries, const identifier_config& config) {
74
75 std::string name = elem.Attribute("name");
77
78 auto child = elem.FirstChildElement();
79 while(child) {
80 if(strcmp(child->Name(), config.point_tag_id.c_str()) == 0 ||
81 strcmp(child->Name(), config.color_point_tag_id.c_str()) == 0 ||
82 strcmp(child->Name(), config.opacity_point_tag_id.c_str()) == 0) {
83 point_info pi = extract_control_point(*child, config);
84
85 if(!(pi.x < 0.0f)) {
86 if(!(pi.r < 0.0f || pi.g < 0.0f || pi.b < 0.0f)) {
87 rgb col(0.0f);
88 col[0] = std::min(pi.r, 1.0f);
89 col[1] = std::min(pi.g, 1.0f);
90 col[2] = std::min(pi.b, 1.0f);
91 // apply gamma correction if requested
92 if(config.apply_gamma) {
93 col[0] = pow(col[0], 2.2f);
94 col[1] = pow(col[1], 2.2f);
95 col[2] = pow(col[2], 2.2f);
96 }
97 cm.add_color_point(pi.x, col);
98 }
99
100 if(!(pi.o < 0.0f)) {
101 cm.add_opacity_point(pi.x, cgv::math::clamp(pi.o, 0.0f, 1.0f));
102 }
103 }
104 }
105
106 child = child->NextSiblingElement();
107 }
108
109 if(!cm.empty())
110 entries.push_back({ name, cm });
111 }
112
113 static void extract_color_maps(const tinyxml2::XMLElement& elem, result& entries, const identifier_config& config) {
114
115 cgv::xml::FindElementByNameVisitor findElementByName("ColorMaps");
116 elem.Accept(&findElementByName);
117
118 if (auto color_maps_elem = findElementByName.Result()) {
119 auto color_map_elem = color_maps_elem->FirstChildElement();
120
121 while (color_map_elem) {
122 if (strcmp(color_map_elem->Name(), config.color_map_tag_id.c_str()) == 0)
123 extract_color_map(*color_map_elem, entries, config);
124 color_map_elem = color_map_elem->NextSiblingElement();
125 }
126 }
127 }
128
129public:
130 static bool read_from_xml(const tinyxml2::XMLElement& elem, result& entries, const identifier_config& config = default_identifier_config()) {
131
132 entries.clear();
133 extract_color_maps(elem, entries, config);
134
135 return !entries.empty();
136 }
137
138 static bool read_from_xml(const tinyxml2::XMLDocument& doc, result& entries, const identifier_config& config = default_identifier_config()) {
139
140 if(const tinyxml2::XMLElement* elem = doc.RootElement())
141 return read_from_xml(*elem, entries, config);
142
143 return false;
144 }
145
146 static bool read_from_xml_string(const std::string& xml, result& entries, const identifier_config& config = default_identifier_config()) {
147
148 tinyxml2::XMLDocument doc;
149 if(doc.Parse(xml.c_str()) == tinyxml2::XML_SUCCESS)
150 return read_from_xml(doc, entries, config);
151
152 return false;
153 }
154
155 static bool read_from_xml_file(const std::string& file_name, result& entries, const identifier_config& config = default_identifier_config()) {
156
157 tinyxml2::XMLDocument doc;
158 if(doc.LoadFile(file_name.c_str()) == tinyxml2::XML_SUCCESS)
159 return read_from_xml(doc, entries, config);
160
161 return false;
162 }
163
164 static bool read_from_image_file(const std::string& file_name, result& entries) {
165
166 entries.clear();
167
168 if(!cgv::utils::file::exists(file_name))
169 return false;
170
173 cgv::media::image::image_reader image_reader(format);
174
175 const std::string name = cgv::utils::file::drop_extension(cgv::utils::file::get_file_name(file_name));
176
177 if(image_reader.read_image(file_name, data)) {
178 auto type_id = format.get_component_type();
179
180 float max_value = 1.0f;
181 if(cgv::type::info::is_integral(type_id)) {
182 switch(cgv::type::info::get_type_size(type_id)) {
183 case 1: max_value = static_cast<float>(0x000000FF); break;
184 case 2: max_value = static_cast<float>(0x0000FFFF); break;
185 case 3: max_value = static_cast<float>(0x00FFFFFF); break;
186 case 4: max_value = static_cast<float>(0xFFFFFFFF); break;
187 default: break;
188 }
189 }
190
192 float step = 1.0f / static_cast<float>(format.get_width() - 1);
193 float t = 0.0f;
194
195 if(format.get_width() > 0 && format.get_height() > 0) {
196 switch(format.get_nr_components()) {
197 case 1u:
198 for(size_t x = 0; x < format.get_width(); ++x) {
199 cm.add_color_point(t, cgv::rgb(data.get<float>(0, 0, x) / max_value));
200 t += step;
201 }
202 break;
203 case 3u:
204 case 4u:
205 for(size_t x = 0; x < format.get_width(); ++x) {
206 float r = data.get<float>(0, 0, x) / max_value;
207 float g = data.get<float>(1, 0, x) / max_value;
208 float b = data.get<float>(2, 0, x) / max_value;
209 cm.add_color_point(t, cgv::rgb(r, g, b));
210 t += step;
211 }
212
213 if(format.get_nr_components() == 4u) {
214 t = 0.0f;
215 for(size_t x = 0; x < format.get_width(); ++x) {
216 cm.add_opacity_point(t, data.get<float>(3, 0, x) / max_value);
217 t += step;
218 }
219 }
220 break;
221 default:
222 break;
223 }
224 }
225
226 entries.push_back({ name, cm });
227 }
228
229 return !entries.empty();
230 }
231};
232
233}
234}
cgv::type::info::TypeId get_component_type() const
return the component type
unsigned int get_nr_components() const
return the number of components
A data_format describes a multidimensional data block of data entries.
Definition data_format.h:17
size_t get_width() const
return the resolution in the first dimension, or 1 if not defined
size_t get_height() const
return the resolution in the second dimension, or 1 if not defined
S get(unsigned ci) const
constant access to the ci-th component
Definition data_view.h:86
the data view gives access to a data array of one, two, three or four dimensions.
Definition data_view.h:153
the image reader chooses a specific reader automatically based on the extension of the given file nam...
Finds a tinyxml2::XMLElement by name.
Definition query.h:27
unsigned int get_type_size(TypeId tid)
function that returns the size of a type specified through TypeId
Definition type_id.cxx:18
the cgv namespace
Definition print.h:11
cgv::media::color< float, cgv::media::RGB > rgb
declare rgb color type with 32 bit components
Definition color.h:853