Shinya Kitaoka 810553
#pragma once
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifndef TSPECTRUM_INCLUDED
Toshihiro Shimizu 890ddd
#define TSPECTRUM_INCLUDED
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tpixelutils.h"
Toshihiro Shimizu 890ddd
#include "tutil.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#undef DVAPI
Toshihiro Shimizu 890ddd
#undef DVVAR
Toshihiro Shimizu 890ddd
#ifdef TCOLOR_EXPORTS
Toshihiro Shimizu 890ddd
#define DVAPI DV_EXPORT_API
Toshihiro Shimizu 890ddd
#define DVVAR DV_EXPORT_VAR
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
#define DVAPI DV_IMPORT_API
Toshihiro Shimizu 890ddd
#define DVVAR DV_IMPORT_VAR
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
e280ae
#ifdef _MSC_VER
Toshihiro Shimizu 890ddd
#pragma warning(disable : 4251)
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <class t=""></class>
Shinya Kitaoka 120a6e
class DVAPI TSpectrumT {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  typedef std::pair<double, t=""> ColorKey;</double,>
Shinya Kitaoka 120a6e
  typedef ColorKey Key;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  typedef std::vector<colorkey> KeyTable;</colorkey>
Shinya Kitaoka 120a6e
  KeyTable m_keys, m_sortedKeys;
Shinya Kitaoka 120a6e
  typedef std::pair<t, t=""> Pair;  // premultiplied/not premultiplied</t,>
Shinya Kitaoka 120a6e
  std::vector<pair> m_samples;</pair>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  inline T getActualValue(double s) {
Shinya Kitaoka 120a6e
    assert(!m_sortedKeys.empty());
Shinya Kitaoka 120a6e
    typename std::vector<colorkey>::const_iterator b;</colorkey>
Shinya Kitaoka 120a6e
    b = std::lower_bound(m_sortedKeys.begin(), m_sortedKeys.end(),
shun-iwasawa d2d38a
                         ColorKey(s, T()),
shun-iwasawa d2d38a
                         [](const ColorKey &a, const ColorKey &b) {
shun-iwasawa d2d38a
                           return a.first < b.first;
luz paz 266edb
                         });  // compare only key positions
shun-iwasawa d2d38a
Shinya Kitaoka 120a6e
    if (b == m_sortedKeys.end())
Shinya Kitaoka 120a6e
      return m_sortedKeys.rbegin()->second;
Shinya Kitaoka 120a6e
    else if (b == m_sortedKeys.begin() || areAlmostEqual(b->first, s))
Shinya Kitaoka 120a6e
      return b->second;
Shinya Kitaoka 120a6e
    else {
Shinya Kitaoka 120a6e
      typename KeyTable::const_iterator a = b;
Shinya Kitaoka 120a6e
      a--;
Shinya Kitaoka 120a6e
      assert(a->first < s && s <= b->first);
Shinya Kitaoka 120a6e
      double f = (s - a->first) / (b->first - a->first);
Shinya Kitaoka 120a6e
      return blend(a->second, b->second, f);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void update() {
Shinya Kitaoka 120a6e
    assert(!m_keys.empty());
Shinya Kitaoka 120a6e
    m_sortedKeys = m_keys;
Shinya Kitaoka 120a6e
    std::sort(m_sortedKeys.begin(), m_sortedKeys.end());
Shinya Kitaoka 120a6e
    if (m_samples.empty()) m_samples.resize(100);
Shinya Kitaoka 120a6e
    int n = m_samples.size();
Shinya Kitaoka 120a6e
    for (int i = 0; i < n; i++) {
Shinya Kitaoka 120a6e
      T v                 = getActualValue((double)i / (double)(n - 1));
Shinya Kitaoka 120a6e
      m_samples[i].second = v;
Shinya Kitaoka 120a6e
      m_samples[i].first  = premultiply(v);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  TSpectrumT() : m_keys(), m_sortedKeys(), m_samples() {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TSpectrumT(const TSpectrumT<t> &s)</t>
Shinya Kitaoka 120a6e
      : m_keys(s.m_keys)
Shinya Kitaoka 120a6e
      , m_sortedKeys(s.m_sortedKeys)
Shinya Kitaoka 120a6e
      , m_samples(s.m_samples) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TSpectrumT(int keyCount, ColorKey keys[], int sampleCount = 100)
Shinya Kitaoka 120a6e
      : m_keys(keys, keys + keyCount) {
Shinya Kitaoka 120a6e
    m_samples.resize(sampleCount);
Shinya Kitaoka 120a6e
    update();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  /*SpectrumT(std::map<double, t=""> &keys, int sampleCount=100)</double,>
Shinya Kitaoka 120a6e
{
Shinya Kitaoka 120a6e
m_keys = keys;
Shinya Kitaoka 120a6e
updateTable(sampleCount);
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
*/
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TSpectrumT(const T &a, const T &b, int sampleCount = 100) {
Shinya Kitaoka 120a6e
    m_keys.push_back(ColorKey(0, a));
Shinya Kitaoka 120a6e
    m_keys.push_back(ColorKey(1, b));
Shinya Kitaoka 120a6e
    m_samples.resize(sampleCount);
Shinya Kitaoka 120a6e
    update();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool operator==(const TSpectrumT<t> &s) const {</t>
Shinya Kitaoka 120a6e
    if (m_keys.size() != s.m_keys.size()) return false;
Shinya Kitaoka 120a6e
    typename KeyTable::const_iterator i0, i1;
Shinya Kitaoka 120a6e
    for (i0 = m_keys.begin(), i1 = s.m_keys.begin(); i0 != m_keys.end();
Shinya Kitaoka 120a6e
         ++i0, ++i1) {
Shinya Kitaoka 120a6e
      assert(i1 != s.m_keys.end());
Shinya Kitaoka 120a6e
      if (i0->first != i1->first) return false;
Shinya Kitaoka 120a6e
      if (i0->second != i1->second) return false;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    return true;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  bool operator!=(const TSpectrumT<t> &s) const { return !operator==(s); }</t>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  T getValue(double s) const  // non premoltiplicati
Toshihiro Shimizu 890ddd
  {
Shinya Kitaoka 120a6e
    assert(!m_keys.empty());
Shinya Kitaoka 120a6e
    int m = m_samples.size();
Shinya Kitaoka 120a6e
    assert(m > 1);
Shinya Kitaoka 120a6e
    if (s <= 0)
Shinya Kitaoka 120a6e
      return m_samples.front().second;
Shinya Kitaoka 120a6e
    else if (s >= 1)
Shinya Kitaoka 120a6e
      return m_samples.back().second;
Shinya Kitaoka 120a6e
    s     = s * (m - 1);
Shinya Kitaoka 120a6e
    int i = tfloor(s);
Shinya Kitaoka 120a6e
    assert(0 <= i && i < m - 1);
Shinya Kitaoka 120a6e
    s -= i;
Shinya Kitaoka 120a6e
    assert(0 <= s && s < 1);
Shinya Kitaoka 120a6e
    T a = m_samples[i].second;
Shinya Kitaoka 120a6e
    T b = m_samples[i + 1].second;
Shinya Kitaoka 120a6e
    return blend<t>(a, b, s);</t>
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  T getPremultipliedValue(double s) const  // non premoltiplicati
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    assert(!m_keys.empty());
Shinya Kitaoka 120a6e
    int m = m_samples.size();
Shinya Kitaoka 120a6e
    assert(m > 1);
Shinya Kitaoka 120a6e
    if (s <= 0)
Shinya Kitaoka 120a6e
      return m_samples.front().first;
Shinya Kitaoka 120a6e
    else if (s >= 1)
Shinya Kitaoka 120a6e
      return m_samples.back().first;
Shinya Kitaoka 120a6e
    s     = s * (m - 1);
Shinya Kitaoka 120a6e
    int i = tfloor(s);
Shinya Kitaoka 120a6e
    assert(0 <= i && i < m - 1);
Shinya Kitaoka 120a6e
    s -= i;
Shinya Kitaoka 120a6e
    assert(0 <= s && s < 1);
Shinya Kitaoka 120a6e
    T a = m_samples[i].first;
Shinya Kitaoka 120a6e
    T b = m_samples[i + 1].first;
Shinya Kitaoka 120a6e
    return blend<t>(a, b, s);</t>
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int getKeyCount() const { return m_keys.size(); }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  Key getKey(int index) const {
Shinya Kitaoka 120a6e
    assert(0 <= index && index < getKeyCount());
Shinya Kitaoka 120a6e
    return m_keys[index];
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void setKey(int index, const Key &key) {
Shinya Kitaoka 120a6e
    assert(0 <= index && index < getKeyCount());
Shinya Kitaoka 120a6e
    assert(0 <= key.first && key.first <= 1);
Shinya Kitaoka 120a6e
    m_keys[index] = key;
Shinya Kitaoka 120a6e
    update();
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void addKey(const Key &key) {
Shinya Kitaoka 120a6e
    m_keys.push_back(key);
Shinya Kitaoka 120a6e
    update();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void removeKey(int index) {
Shinya Kitaoka 120a6e
    if (m_keys.size() <= 1) return;
Shinya Kitaoka 120a6e
    assert(0 <= index && index < getKeyCount());
Shinya Kitaoka 120a6e
    m_keys.erase(m_keys.begin() + index);
Shinya Kitaoka 120a6e
    update();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Campbell Barton 8c6c57
DVAPI TSpectrumT<tpixel64> convert(const TSpectrumT<tpixel32> &s);</tpixel32></tpixel64>
Campbell Barton 8c6c57
Shinya Kitaoka 9f5a1b
#ifdef _WIN32
Toshihiro Shimizu 890ddd
template class DVAPI TSpectrumT<tpixel32>;</tpixel32>
Toshihiro Shimizu 890ddd
template class DVAPI TSpectrumT<tpixel64>;</tpixel64>
shun-iwasawa 481b59
template class DVAPI TSpectrumT<tpixelf>;</tpixelf>
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef TSpectrumT<tpixel32> TSpectrum;</tpixel32>
Toshihiro Shimizu 890ddd
typedef TSpectrumT<tpixel64> TSpectrum64;</tpixel64>
shun-iwasawa 481b59
typedef TSpectrumT<tpixelf> TSpectrumF;</tpixelf>
Toshihiro Shimizu 890ddd
e280ae
#ifdef _MSC_VER
Toshihiro Shimizu 890ddd
#pragma warning(default : 4251)
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif