/* Copyright (C) 2013 Carl Hetherington This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config.h" #include "colour_conversion.h" #include "util.h" #include "md5_digester.h" #include #include #include #include #include #include #include "i18n.h" using std::list; using std::string; using std::cout; using std::vector; using boost::shared_ptr; using boost::optional; using boost::dynamic_pointer_cast; using dcp::raw_convert; ColourConversion::ColourConversion () : dcp::ColourConversion (dcp::ColourConversion::srgb_to_xyz ()) { } ColourConversion::ColourConversion (dcp::ColourConversion conversion_) : dcp::ColourConversion (conversion_) { } ColourConversion::ColourConversion (cxml::NodePtr node) { shared_ptr in; cxml::ConstNodePtr in_node = node->node_child ("InputTransferFunction"); string in_type = in_node->string_child ("Type"); if (in_type == "Gamma") { _in.reset (new dcp::GammaTransferFunction (false, in_node->number_child ("Gamma"))); } else if (in_type == "ModifiedGamma") { _in.reset (new dcp::ModifiedGammaTransferFunction ( false, in_node->number_child ("Power"), in_node->number_child ("Threshold"), in_node->number_child ("A"), in_node->number_child ("B") )); } list m = node->node_children ("Matrix"); for (list::iterator i = m.begin(); i != m.end(); ++i) { int const ti = (*i)->number_attribute ("i"); int const tj = (*i)->number_attribute ("j"); _matrix(ti, tj) = raw_convert ((*i)->content ()); } _out.reset (new dcp::GammaTransferFunction (true, node->number_child ("OutputGamma"))); } boost::optional ColourConversion::from_xml (cxml::NodePtr node) { if (!node->optional_node_child ("InputTransferFunction")) { return boost::optional (); } return ColourConversion (node); } void ColourConversion::as_xml (xmlpp::Node* node) const { xmlpp::Node* in_node = node->add_child ("InputTransferFunction"); if (dynamic_pointer_cast (_in)) { shared_ptr tf = dynamic_pointer_cast (_in); in_node->add_child("Type")->add_child_text ("Gamma"); in_node->add_child("Gamma")->add_child_text (raw_convert (tf->gamma ())); } else if (dynamic_pointer_cast (_in)) { shared_ptr tf = dynamic_pointer_cast (_in); in_node->add_child("Type")->add_child_text ("ModifiedGamma"); in_node->add_child("Power")->add_child_text (raw_convert (tf->power ())); in_node->add_child("Threshold")->add_child_text (raw_convert (tf->threshold ())); in_node->add_child("A")->add_child_text (raw_convert (tf->A ())); in_node->add_child("B")->add_child_text (raw_convert (tf->B ())); } boost::numeric::ublas::matrix matrix = _matrix; for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { xmlpp::Element* m = node->add_child("Matrix"); m->set_attribute ("i", raw_convert (i)); m->set_attribute ("j", raw_convert (j)); m->add_child_text (raw_convert (matrix (i, j))); } } node->add_child("OutputGamma")->add_child_text (raw_convert (dynamic_pointer_cast (_out)->gamma ())); } optional ColourConversion::preset () const { vector presets = Config::instance()->colour_conversions (); size_t i = 0; while (i < presets.size() && (presets[i].conversion != *this)) { ++i; } if (i >= presets.size ()) { return optional (); } return i; } string ColourConversion::identifier () const { MD5Digester digester; if (dynamic_pointer_cast (_in)) { shared_ptr tf = dynamic_pointer_cast (_in); digester.add (tf->gamma ()); } else if (dynamic_pointer_cast (_in)) { shared_ptr tf = dynamic_pointer_cast (_in); digester.add (tf->power ()); digester.add (tf->threshold ()); digester.add (tf->A ()); digester.add (tf->B ()); } boost::numeric::ublas::matrix matrix = _matrix; for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { digester.add (matrix (i, j)); } } digester.add (dynamic_pointer_cast (_out)->gamma ()); return digester.get (); } PresetColourConversion::PresetColourConversion () : name (_("Untitled")) { } PresetColourConversion::PresetColourConversion (string n, dcp::ColourConversion conversion_) : name (n) , conversion (conversion_) { } PresetColourConversion::PresetColourConversion (cxml::NodePtr node) : conversion (node) { name = node->string_child ("Name"); } void PresetColourConversion::as_xml (xmlpp::Node* node) const { conversion.as_xml (node); node->add_child("Name")->add_child_text (name); } bool operator== (ColourConversion const & a, ColourConversion const & b) { return a.about_equal (b, 1e-6); } bool operator!= (ColourConversion const & a, ColourConversion const & b) { return !(a == b); }