Switch to Lut1d
This commit is contained in:
75
lut.h
75
lut.h
@@ -15,6 +15,10 @@ class LutBase {
|
||||
|
||||
template <int32_t X, int32_t Y, int32_t C>
|
||||
std::unique_ptr<Image<X, Y, C>> MapImage(const Image<X, Y, C>& in) const;
|
||||
|
||||
protected:
|
||||
static constexpr std::pair<int32_t, int32_t> FindChannelRoot(int32_t value, int32_t points);
|
||||
static constexpr int32_t BlockSize(int32_t points);
|
||||
};
|
||||
|
||||
template <int32_t X, int32_t Y, int32_t C>
|
||||
@@ -31,6 +35,59 @@ std::unique_ptr<Image<X, Y, C>> LutBase::MapImage(const Image<X, Y, C>& in) cons
|
||||
return out;
|
||||
}
|
||||
|
||||
constexpr int32_t LutBase::BlockSize(int32_t points) {
|
||||
return (kMaxColor + 1) / (points - 1);
|
||||
}
|
||||
|
||||
constexpr std::pair<int32_t, int32_t> LutBase::FindChannelRoot(int32_t value, int32_t points) {
|
||||
// points - 1 is the last point index. Since we're going to find the region
|
||||
// around this point by adding to the root, we need to be at least 1 less
|
||||
// than that.
|
||||
int32_t index = std::min(points - 2, value / BlockSize(points));
|
||||
return std::make_pair(index, value - (index * BlockSize(points)));
|
||||
}
|
||||
|
||||
|
||||
template <int32_t X>
|
||||
class Lut1d : public Array<Color<3>, X>, public LutBase {
|
||||
public:
|
||||
static Lut1d<X> Identity();
|
||||
|
||||
Color<3> MapColor(const Color<3>& in) const override;
|
||||
};
|
||||
|
||||
typedef Lut1d<2> MinimalLut1d;
|
||||
|
||||
template <int32_t X>
|
||||
Lut1d<X> Lut1d<X>::Identity() {
|
||||
Lut1d<X> ret;
|
||||
|
||||
Color<3> color;
|
||||
for (int32_t x = 0; x < X; ++x) {
|
||||
color.at(0) = color.at(1) = color.at(2) = std::min(kMaxColor, BlockSize(X) * x);
|
||||
ret.at(x) = color;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <int32_t X>
|
||||
Color<3> Lut1d<X>::MapColor(const Color<3>& in) const {
|
||||
Color<3> ret;
|
||||
|
||||
for (int32_t c = 0; c < 3; ++c) {
|
||||
const auto root_rem = FindChannelRoot(in.at(c), X);
|
||||
const auto& root = root_rem.first;
|
||||
const auto& rem = root_rem.second;
|
||||
ret.at(c) = Interpolate(
|
||||
this->at(root + 0).at(c),
|
||||
this->at(root + 1).at(c),
|
||||
rem, BlockSize(X));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
template <int32_t X, int32_t Y, int32_t Z>
|
||||
class Lut3d : public Array<Array<Array<Color<3>, X>, Y>, Z>, public LutBase {
|
||||
@@ -42,12 +99,8 @@ class Lut3d : public Array<Array<Array<Color<3>, X>, Y>, Z>, public LutBase {
|
||||
private:
|
||||
// Return value is (root_indices, remainders)
|
||||
constexpr static std::pair<Coord<3>, Coord<3>> FindRoot(const Color<3>& in);
|
||||
constexpr static std::pair<int32_t, int32_t> FindChannelRoot(int32_t value, int32_t points);
|
||||
|
||||
constexpr static int32_t BlockSize(int32_t points);
|
||||
};
|
||||
|
||||
// Minimum size LUT
|
||||
typedef Lut3d<2, 2, 2> MinimalLut3d;
|
||||
|
||||
template <int32_t X, int32_t Y, int32_t Z>
|
||||
@@ -116,17 +169,3 @@ constexpr std::pair<Coord<3>, Coord<3>> Lut3d<X, Y, Z>::FindRoot(const Color<3>&
|
||||
{{{{root_x.second, root_y.second, root_z.second}}}},
|
||||
};
|
||||
}
|
||||
|
||||
template <int32_t X, int32_t Y, int32_t Z>
|
||||
constexpr std::pair<int32_t, int32_t> Lut3d<X, Y, Z>::FindChannelRoot(const int32_t value, const int32_t points) {
|
||||
// points - 1 is the last point index. Since we're going to fidn the cube
|
||||
// around this point by adding to the root, we need to be at least 1 less
|
||||
// than that.
|
||||
int32_t index = std::min(points - 2, value / BlockSize(points));
|
||||
return std::make_pair(index, value - (index * BlockSize(points)));
|
||||
}
|
||||
|
||||
template <int32_t X, int32_t Y, int32_t Z>
|
||||
constexpr int32_t Lut3d<X, Y, Z>::BlockSize(int32_t points) {
|
||||
return (kMaxColor + 1) / (points - 1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user