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;
40 typedef std::vector<std::pair<std::string, cgv::render::color_map>> result;
51 static void extract_value(
const tinyxml2::XMLElement& elem,
const std::string& name,
bool as_float,
float& value) {
54 elem.QueryFloatAttribute(name.c_str(), &value);
57 if(elem.QueryIntAttribute(name.c_str(), &temp) == tinyxml2::XML_SUCCESS)
58 value =
static_cast<float>(temp) / 255.0f;
62 static point_info extract_control_point(
const tinyxml2::XMLElement& elem,
const identifier_config& config) {
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);
73 static void extract_color_map(
const tinyxml2::XMLElement& elem, result& entries,
const identifier_config& config) {
75 std::string name = elem.Attribute(
"name");
78 auto child = elem.FirstChildElement();
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);
86 if(!(pi.r < 0.0f || pi.g < 0.0f || pi.b < 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);
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);
97 cm.add_color_point(pi.x, col);
101 cm.add_opacity_point(pi.x, cgv::math::clamp(pi.o, 0.0f, 1.0f));
106 child = child->NextSiblingElement();
110 entries.push_back({ name, cm });
113 static void extract_color_maps(
const tinyxml2::XMLElement& elem, result& entries,
const identifier_config& config) {
116 elem.Accept(&findElementByName);
118 if (
auto color_maps_elem = findElementByName.Result()) {
119 auto color_map_elem = color_maps_elem->FirstChildElement();
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();
130 static bool read_from_xml(
const tinyxml2::XMLElement& elem, result& entries,
const identifier_config& config = default_identifier_config()) {
133 extract_color_maps(elem, entries, config);
135 return !entries.empty();
138 static bool read_from_xml(
const tinyxml2::XMLDocument& doc, result& entries,
const identifier_config& config = default_identifier_config()) {
140 if(
const tinyxml2::XMLElement* elem = doc.RootElement())
141 return read_from_xml(*elem, entries, config);
146 static bool read_from_xml_string(
const std::string& xml, result& entries,
const identifier_config& config = default_identifier_config()) {
148 tinyxml2::XMLDocument doc;
149 if(doc.Parse(xml.c_str()) == tinyxml2::XML_SUCCESS)
150 return read_from_xml(doc, entries, config);
155 static bool read_from_xml_file(
const std::string& file_name, result& entries,
const identifier_config& config = default_identifier_config()) {
157 tinyxml2::XMLDocument doc;
158 if(doc.LoadFile(file_name.c_str()) == tinyxml2::XML_SUCCESS)
159 return read_from_xml(doc, entries, config);
164 static bool read_from_image_file(
const std::string& file_name, result& entries) {
168 if(!cgv::utils::file::exists(file_name))
175 const std::string name = cgv::utils::file::drop_extension(cgv::utils::file::get_file_name(file_name));
177 if(image_reader.read_image(file_name, data)) {
180 float max_value = 1.0f;
181 if(cgv::type::info::is_integral(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;
192 float step = 1.0f /
static_cast<float>(format.
get_width() - 1);
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));
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));
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);
226 entries.push_back({ name, cm });
229 return !entries.empty();