SVN commit 755289 by tamponi: Now, in theory, you can even use quint16 and quint8 as channel type for the colorspace, but it gives very bad conversions (they're not large enough to store all the values). M +26 -21 channel_converter.h M +14 -11 kis_ks_colorspace.h M +7 -7 tests/channel_converter_test.cpp --- trunk/koffice/krita/plugins/painterlyframework/channel_converter.h #755288:755289 @@ -25,7 +25,9 @@ #include #include -template< typename TYPE > +#include + +template< typename _TYPE_ > class ChannelConverter { public: @@ -33,8 +35,8 @@ ChannelConverter(const double &Kblack, const double &Sblack); ~ChannelConverter(); - inline void KSToReflectance(const TYPE &K, const TYPE &S, double &R) const; - inline void reflectanceToKS(const double &R, TYPE &K, TYPE &S) const; + inline void KSToReflectance(const _TYPE_ &K, const _TYPE_ &S, double &R) const; + inline void reflectanceToKS(const double &R, _TYPE_ &K, _TYPE_ &S) const; private: double Kb, Sb; @@ -51,14 +53,15 @@ inline double S(const double &R) const; }; -template< typename TYPE > -ChannelConverter::ChannelConverter(const double &Kblack, const double &Sblack) +template< typename _TYPE_ > +ChannelConverter<_TYPE_>::ChannelConverter(const double &Kblack, const double &Sblack) : Kb(Kblack), Sb(Sblack) { double q1, q2, k1, k2, D, Sh; double r0; // Represent the reflectance of the reference black (no, it's not zero) - KSToReflectance(Kb, Sb, r0); + KSToReflectance(KoColorSpaceMaths::scaleToA(Kb), + KoColorSpaceMaths::scaleToA(Sb), r0); q1 = Kb / ( 1.0 + Kb*PHI(r0) ); k1 = 1.0 + q1 - sqrt( q1*q1 + 2.0*q1 ); @@ -96,13 +99,13 @@ gsl_vector_free(x); } -template< typename TYPE > -ChannelConverter::~ChannelConverter() +template< typename _TYPE_ > +ChannelConverter<_TYPE_>::~ChannelConverter() { } -template< typename TYPE > -inline double ChannelConverter::K(const double &R) const +template< typename _TYPE_ > +inline double ChannelConverter<_TYPE_>::K(const double &R) const { if (R <= 0.5) return ( 1.0 / (PHI(W(R))-PHI(R)) ); @@ -110,8 +113,8 @@ return ( S(R)*PSI(R) ); } -template< typename TYPE > -inline double ChannelConverter::S(const double &R) const +template< typename _TYPE_ > +inline double ChannelConverter<_TYPE_>::S(const double &R) const { if (R > 0.5) return ( Kb - Sb*PSI(B(R)) ) / ( PSI(B(R)) - PSI(R) ); @@ -119,28 +122,30 @@ return ( K(R)*PHI(R) ); } -template< typename TYPE > -inline void ChannelConverter::KSToReflectance(const TYPE &K, const TYPE &S, double &R) const +template< typename _TYPE_ > +inline void ChannelConverter<_TYPE_>::KSToReflectance(const _TYPE_ &K, const _TYPE_ &S, double &R) const { - if (S == 0.0) { + double k = KoColorSpaceMaths<_TYPE_,double>::scaleToA(K); + double s = KoColorSpaceMaths<_TYPE_,double>::scaleToA(S); + if (s == 0.0) { R = 0.0; return; } - if (K == 0.0) { + if (k == 0.0) { R = 1.0; return; } - const double Q = (double)(K/S); + const double Q = k/s; R = 1.0 + Q - sqrt( Q*Q + 2.0*Q ); } -template< typename TYPE > -inline void ChannelConverter::reflectanceToKS(const double &R, TYPE &K, TYPE &S) const +template< typename _TYPE_ > +inline void ChannelConverter<_TYPE_>::reflectanceToKS(const double &R, _TYPE_ &K, _TYPE_ &S) const { - K = (TYPE)(this->K(R)); - S = (TYPE)(this->S(R)); + K = KoColorSpaceMaths::scaleToA(this->K(R)); + S = KoColorSpaceMaths::scaleToA(this->S(R)); } #endif // CHANNEL_CONVERTER_H_ --- trunk/koffice/krita/plugins/painterlyframework/kis_ks_colorspace.h #755288:755289 @@ -68,14 +68,17 @@ QString id; QByteArray name; - if (sizeof(_TYPE_) == 4) { - id = QString("F32"); - name = QString("32 Bits Float").toUtf8(); + switch (KoColorSpaceMathsTraits<_TYPE_>::channelValueType) { + case KoChannelInfo::FLOAT32: + id = QString("F32"); + name = QString("32 Bits Float").toUtf8(); + break; + case KoChannelInfo::FLOAT16: + id = QString("F16"); + name = QString("16 Bits Float").toUtf8(); + break; + default: break; } - if (sizeof(_TYPE_) == 2) { - id = QString("F16"); - name = QString("16 Bits Float").toUtf8(); - } return KoID(id, i18n(name.data())); } @@ -162,8 +165,8 @@ { QDomElement labElt = doc.createElement("KS"+QString::number(_N_)); for (uint i = 0; i < _N_; i++) { - labElt.setAttribute("K"+QString::number(i), (double)CSTrait::K(pixel,i)); - labElt.setAttribute("S"+QString::number(i), (double)CSTrait::S(pixel,i)); + labElt.setAttribute("K"+QString::number(i), KoColorSpaceMaths<_TYPE_,double>::scaleToA(CSTrait::K(pixel,i))); + labElt.setAttribute("S"+QString::number(i), KoColorSpaceMaths<_TYPE_,double>::scaleToA(CSTrait::S(pixel,i))); } labElt.setAttribute("space", profile()->name()); colorElt.appendChild(labElt); @@ -173,8 +176,8 @@ void KisKSColorSpace<_TYPE_,_N_>::colorFromXML(quint8 *pixel, const QDomElement &elt) const { for (uint i = 0; i < _N_; i++) { - CSTrait::K(pixel,i) = elt.attribute("K"+QString::number(i)).toFloat(); - CSTrait::S(pixel,i) = elt.attribute("S"+QString::number(i)).toFloat(); + CSTrait::K(pixel,i) = KoColorSpaceMaths::scaleToA(elt.attribute("K"+QString::number(i)).toDouble()); + CSTrait::S(pixel,i) = KoColorSpaceMaths::scaleToA(elt.attribute("S"+QString::number(i)).toDouble()); } } --- trunk/koffice/krita/plugins/painterlyframework/tests/channel_converter_test.cpp #755288:755289 @@ -27,27 +27,27 @@ void ChannelConverterTest::testKSReflectance() { - ChannelConverter c(4.3, 0.14); - double K, S, R; + ChannelConverter c(4.3, 0.14); + float K, S; double R; R = 0.4999999999999; c.reflectanceToKS(R, K, S); qDebug() << "Reflectance " << R << "; K = " << K << ", S = " << S; - QCOMPARE((S/K), (R*2.0/pow(1-R,2))); + QCOMPARE((double)(S/K), (R*2.0/pow(1-R,2))); R = 0.5000000000001; c.reflectanceToKS(R, K, S); qDebug() << "Reflectance " << R << "; K = " << K << ", S = " << S; - QCOMPARE((S/K), (R*2.0/pow(1-R,2))); + QCOMPARE((double)(S/K), (R*2.0/pow(1-R,2))); for (int i = 0; i <= 100; i++) { R = (double)i/100.0; c.reflectanceToKS(R, K, S); qDebug() << "Reflectance " << R << "; K = " << K << ", S = " << S; if ( i <= 50 ) - QCOMPARE((S/K), (2.0*R*pow(1-R,-2))); + QCOMPARE((double)(S/K), (2.0*R*pow(1-R,-2))); else - QCOMPARE((K/S), (0.5*pow(1-R, 2)/R)); + QCOMPARE((double)(K/S), (0.5*pow(1-R, 2)/R)); } // KSToReflectance @@ -65,7 +65,7 @@ c.KSToReflectance(K, S, R); qDebug() << "K " << K << ", S " << S << "; R = " << R; QVERIFY(R > 0.0 && R < 1.0); - QCOMPARE((S/K), (R*2.0/pow(1-R,2))); + QCOMPARE((double)(S/K), (R*2.0/pow(1-R,2))); } }