Signed conversion checkpoint
This commit is contained in:
25
color.h
25
color.h
@@ -7,28 +7,30 @@
|
|||||||
|
|
||||||
#include "intmath.h"
|
#include "intmath.h"
|
||||||
|
|
||||||
constexpr uint32_t kMaxColor = UINT16_MAX;
|
constexpr int32_t kMinColor = 0;
|
||||||
|
constexpr int32_t kMaxColor = UINT16_MAX;
|
||||||
|
|
||||||
// 32-bit for compiler convenience, but values are 16-bit
|
// 32-bit for compiler convenience, but values are 16-bit
|
||||||
template <uint32_t C>
|
template <uint32_t C>
|
||||||
struct Color : public std::array<uint32_t, C> {
|
struct Color : public std::array<int32_t, C> {
|
||||||
constexpr uint32_t Difference(const Color<C>& other) const;
|
constexpr uint32_t AbsDiff(const Color<C>& other) const;
|
||||||
constexpr Color<C> Interpolate(const Color<C>& other, uint32_t mul, uint32_t div) const;
|
constexpr Color<C> Interpolate(const Color<C>& other, int32_t mul, int32_t div) const;
|
||||||
|
constexpr Color<C> Crop() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RgbColor : public Color<3> {};
|
struct RgbColor : public Color<3> {};
|
||||||
|
|
||||||
template <uint32_t C>
|
template <uint32_t C>
|
||||||
constexpr uint32_t Color<C>::Difference(const Color<C>& other) const {
|
constexpr uint32_t Color<C>::AbsDiff(const Color<C>& other) const {
|
||||||
uint32_t diff = 0;
|
uint32_t diff = 0;
|
||||||
for (uint32_t c = 0; c < C; ++c) {
|
for (uint32_t c = 0; c < C; ++c) {
|
||||||
diff += AbsDiff(this->at(c), other.at(c));
|
diff += static_cast<uint32_t>(::AbsDiff(this->at(c), other.at(c)));
|
||||||
}
|
}
|
||||||
return diff;
|
return diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <uint32_t C>
|
template <uint32_t C>
|
||||||
constexpr Color<C> Color<C>::Interpolate(const Color<C>& other, uint32_t mul, uint32_t div) const {
|
constexpr Color<C> Color<C>::Interpolate(const Color<C>& other, int32_t mul, int32_t div) const {
|
||||||
Color<C> ret;
|
Color<C> ret;
|
||||||
for (uint32_t c = 0; c < C; ++c) {
|
for (uint32_t c = 0; c < C; ++c) {
|
||||||
ret.at(c) = ::Interpolate(this->at(c), other.at(c), mul, div);
|
ret.at(c) = ::Interpolate(this->at(c), other.at(c), mul, div);
|
||||||
@@ -36,6 +38,15 @@ constexpr Color<C> Color<C>::Interpolate(const Color<C>& other, uint32_t mul, ui
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <uint32_t C>
|
||||||
|
constexpr Color<C> Color<C>::Crop() const {
|
||||||
|
Color<C> ret;
|
||||||
|
for (uint32_t c = 0; c < C; ++c) {
|
||||||
|
ret.at(c) = std::max(kMinColor, std::min(kMaxColor, this->at(c)));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
template <uint32_t C>
|
template <uint32_t C>
|
||||||
std::ostream& operator<<(std::ostream& os, const Color<C>& color) {
|
std::ostream& operator<<(std::ostream& os, const Color<C>& color) {
|
||||||
os << std::hex << std::setfill('0') << "Color(";
|
os << std::hex << std::setfill('0') << "Color(";
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ std::array<Coord<2>, kColorCheckerSrgb.size()> FindClosest(const Image<X, Y, C>&
|
|||||||
const auto& pixel = row.at(x);
|
const auto& pixel = row.at(x);
|
||||||
|
|
||||||
for (uint32_t cc = 0; cc < kColorCheckerSrgb.size(); ++cc) {
|
for (uint32_t cc = 0; cc < kColorCheckerSrgb.size(); ++cc) {
|
||||||
auto pixel_diff = pixel.Difference(kColorCheckerSrgb.at(cc));
|
auto pixel_diff = pixel.AbsDiff(kColorCheckerSrgb.at(cc));
|
||||||
if (pixel_diff < diff.at(cc)) {
|
if (pixel_diff < diff.at(cc)) {
|
||||||
diff.at(cc) = pixel_diff;
|
diff.at(cc) = pixel_diff;
|
||||||
closest.at(cc) = {{{x, y}}};
|
closest.at(cc) = {{{x, y}}};
|
||||||
@@ -82,7 +82,7 @@ uint32_t ScoreImage(const Image<X, Y, C>& image) {
|
|||||||
const auto& pixel = row.at(x);
|
const auto& pixel = row.at(x);
|
||||||
|
|
||||||
for (uint32_t cc = 0; cc < kColorCheckerSrgb.size(); ++cc) {
|
for (uint32_t cc = 0; cc < kColorCheckerSrgb.size(); ++cc) {
|
||||||
auto pixel_diff = pixel.Difference(kColorCheckerSrgb.at(cc));
|
auto pixel_diff = pixel.AbsDiff(kColorCheckerSrgb.at(cc));
|
||||||
if (pixel_diff < diff.at(cc)) {
|
if (pixel_diff < diff.at(cc)) {
|
||||||
diff.at(cc) = pixel_diff;
|
diff.at(cc) = pixel_diff;
|
||||||
}
|
}
|
||||||
@@ -133,18 +133,18 @@ uint32_t OptimizeLut(const Image<IMG_X, IMG_Y, C>& image, Lut3d<LUT_X, LUT_Y, LU
|
|||||||
for (uint32_t c = 0; c < C; ++c) {
|
for (uint32_t c = 0; c < C; ++c) {
|
||||||
auto& channel = color.at(c);
|
auto& channel = color.at(c);
|
||||||
|
|
||||||
auto min = FindPossibleMinimum<uint32_t, uint32_t, 4>(
|
auto min = FindPossibleMinimum<int32_t, int32_t, 8>(
|
||||||
0, UINT16_MAX,
|
-UINT16_MAX, UINT16_MAX * 2,
|
||||||
[&image, &snapshot, x, y, z, c](uint32_t val) {
|
[&image, &snapshot, x, y, z, c](int32_t val) {
|
||||||
auto test_lut = snapshot;
|
auto test_lut = snapshot;
|
||||||
test_lut.at(x).at(y).at(z).at(c) = val;
|
test_lut.at(x).at(y).at(z).at(c) = val;
|
||||||
return ScoreImage(*test_lut.MapImage(image));
|
return ScoreImage(*test_lut.MapImage(image));
|
||||||
});
|
});
|
||||||
// Magic value of 8 is the number of points making up a square, so the number
|
// Magic value of 8 is the number of points making up a square, so the number
|
||||||
// of points that control any given given LUT mapping.
|
// of points that control any given given LUT mapping.
|
||||||
auto new_value = Interpolate(channel, min, UINT32_C(1), UINT32_C(8));
|
auto new_value = Interpolate(channel, min, INT32_C(1), INT32_C(8));
|
||||||
std::cout << "\tC" << c << ": " << channel << " -> " << new_value << " (interpolated from " << min << ")" << std::endl;
|
std::cout << "\tC" << c << ": " << channel << " -> " << new_value << " (interpolated from " << min << ")" << std::endl;
|
||||||
diff += AbsDiff(channel, new_value);
|
diff += static_cast<uint32_t>(AbsDiff(channel, new_value));
|
||||||
channel = new_value;
|
channel = new_value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,14 +2,10 @@
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr T AbsDiff(T a, T b) {
|
constexpr T AbsDiff(T a, T b) {
|
||||||
return (a > b) ? (a - b) : (b - a);
|
return std::abs(b - a);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr T Interpolate(T val0, T val1, T mul, T div) {
|
constexpr T Interpolate(T val0, T val1, T mul, T div) {
|
||||||
if (val1 > val0) {
|
return val0 + ((mul * (val1 - val0)) / div);
|
||||||
return val0 + ((mul * (val1 - val0)) / div);
|
|
||||||
} else {
|
|
||||||
return val0 - ((mul * (val0 - val1)) / div);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
26
lut.h
26
lut.h
@@ -32,14 +32,14 @@ Lut3d<X, Y, Z> Lut3d<X, Y, Z>::Identity() {
|
|||||||
Color<3> color;
|
Color<3> color;
|
||||||
for (uint32_t x = 0; x < X; ++x) {
|
for (uint32_t x = 0; x < X; ++x) {
|
||||||
auto& rect = ret.at(x);
|
auto& rect = ret.at(x);
|
||||||
color.at(0) = std::min(kMaxColor, BlockSize(X) * x);
|
color.at(0) = std::min(kMaxColor, static_cast<int32_t>(BlockSize(X) * x));
|
||||||
|
|
||||||
for (uint32_t y = 0; y < Y; ++y) {
|
for (uint32_t y = 0; y < Y; ++y) {
|
||||||
auto& row = rect.at(y);
|
auto& row = rect.at(y);
|
||||||
color.at(1) = std::min(kMaxColor, BlockSize(Y) * y);
|
color.at(1) = std::min(kMaxColor, static_cast<int32_t>(BlockSize(Y) * y));
|
||||||
|
|
||||||
for (uint32_t z = 0; z < Z; ++z) {
|
for (uint32_t z = 0; z < Z; ++z) {
|
||||||
color.at(2) = std::min(kMaxColor, BlockSize(Z) * z);
|
color.at(2) = std::min(kMaxColor, static_cast<int32_t>(BlockSize(Z) * z));
|
||||||
row.at(z) = color;
|
row.at(z) = color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,31 +58,31 @@ Color<3> Lut3d<X, Y, Z>::MapColor(const Color<3>& in) const {
|
|||||||
auto inter00 =
|
auto inter00 =
|
||||||
this->at(root.at(0) + 0).at(root.at(1) + 0).at(root.at(2) + 0).Interpolate(
|
this->at(root.at(0) + 0).at(root.at(1) + 0).at(root.at(2) + 0).Interpolate(
|
||||||
this->at(root.at(0) + 1).at(root.at(1) + 0).at(root.at(2) + 0),
|
this->at(root.at(0) + 1).at(root.at(1) + 0).at(root.at(2) + 0),
|
||||||
rem.at(0),
|
static_cast<int32_t>(rem.at(0)),
|
||||||
BlockSize(X));
|
BlockSize(X));
|
||||||
|
|
||||||
auto inter01 =
|
auto inter01 =
|
||||||
this->at(root.at(0) + 0).at(root.at(1) + 0).at(root.at(2) + 1).Interpolate(
|
this->at(root.at(0) + 0).at(root.at(1) + 0).at(root.at(2) + 1).Interpolate(
|
||||||
this->at(root.at(0) + 1).at(root.at(1) + 0).at(root.at(2) + 1),
|
this->at(root.at(0) + 1).at(root.at(1) + 0).at(root.at(2) + 1),
|
||||||
rem.at(0),
|
static_cast<int32_t>(rem.at(0)),
|
||||||
BlockSize(X));
|
BlockSize(X));
|
||||||
|
|
||||||
auto inter10 =
|
auto inter10 =
|
||||||
this->at(root.at(0) + 0).at(root.at(1) + 1).at(root.at(2) + 0).Interpolate(
|
this->at(root.at(0) + 0).at(root.at(1) + 1).at(root.at(2) + 0).Interpolate(
|
||||||
this->at(root.at(0) + 1).at(root.at(1) + 1).at(root.at(2) + 0),
|
this->at(root.at(0) + 1).at(root.at(1) + 1).at(root.at(2) + 0),
|
||||||
rem.at(0),
|
static_cast<int32_t>(rem.at(0)),
|
||||||
BlockSize(X));
|
BlockSize(X));
|
||||||
|
|
||||||
auto inter11 =
|
auto inter11 =
|
||||||
this->at(root.at(0) + 0).at(root.at(1) + 1).at(root.at(2) + 1).Interpolate(
|
this->at(root.at(0) + 0).at(root.at(1) + 1).at(root.at(2) + 1).Interpolate(
|
||||||
this->at(root.at(0) + 1).at(root.at(1) + 1).at(root.at(2) + 1),
|
this->at(root.at(0) + 1).at(root.at(1) + 1).at(root.at(2) + 1),
|
||||||
rem.at(0),
|
static_cast<int32_t>(rem.at(0)),
|
||||||
BlockSize(X));
|
BlockSize(X));
|
||||||
|
|
||||||
auto inter0 = inter00.Interpolate(inter10, rem.at(1), BlockSize(Y));
|
auto inter0 = inter00.Interpolate(inter10, static_cast<int32_t>(rem.at(1)), BlockSize(Y));
|
||||||
auto inter1 = inter01.Interpolate(inter11, rem.at(1), BlockSize(Y));
|
auto inter1 = inter01.Interpolate(inter11, static_cast<int32_t>(rem.at(1)), BlockSize(Y));
|
||||||
|
|
||||||
return inter0.Interpolate(inter1, rem.at(2), BlockSize(Z));
|
return inter0.Interpolate(inter1, static_cast<int32_t>(rem.at(2)), BlockSize(Z)).Crop();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <uint32_t X, uint32_t Y, uint32_t Z>
|
template <uint32_t X, uint32_t Y, uint32_t Z>
|
||||||
@@ -102,9 +102,9 @@ std::unique_ptr<Image<IMG_X, IMG_Y, C>> Lut3d<X, Y, Z>::MapImage(const Image<IMG
|
|||||||
|
|
||||||
template <uint32_t X, uint32_t Y, uint32_t Z>
|
template <uint32_t X, uint32_t Y, uint32_t Z>
|
||||||
constexpr std::pair<Coord<3>, Coord<3>> Lut3d<X, Y, Z>::FindRoot(const Color<3>& in) {
|
constexpr std::pair<Coord<3>, Coord<3>> Lut3d<X, Y, Z>::FindRoot(const Color<3>& in) {
|
||||||
auto root_x = FindChannelRoot(in.at(0), X);
|
auto root_x = FindChannelRoot(static_cast<uint32_t>(in.at(0)), X);
|
||||||
auto root_y = FindChannelRoot(in.at(1), Y);
|
auto root_y = FindChannelRoot(static_cast<uint32_t>(in.at(1)), Y);
|
||||||
auto root_z = FindChannelRoot(in.at(2), Z);
|
auto root_z = FindChannelRoot(static_cast<uint32_t>(in.at(2)), Z);
|
||||||
return {
|
return {
|
||||||
{{{root_x.first, root_y.first, root_z.first}}},
|
{{{root_x.first, root_y.first, root_z.first}}},
|
||||||
{{{root_x.second, root_y.second, root_z.second}}},
|
{{{root_x.second, root_y.second, root_z.second}}},
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ struct Range {
|
|||||||
// Since it does a non-exhaustive search, can be fooled by distributions with
|
// Since it does a non-exhaustive search, can be fooled by distributions with
|
||||||
// multiple peaks, especially those with the minimum in a narrow valley and
|
// multiple peaks, especially those with the minimum in a narrow valley and
|
||||||
// other wider valleys.
|
// other wider valleys.
|
||||||
template <typename I, typename O, uint32_t P>
|
template <typename I, typename O, int32_t P>
|
||||||
I FindPossibleMinimum(I min, I max, std::function<O(I)> callback) {
|
I FindPossibleMinimum(I min, I max, std::function<O(I)> callback) {
|
||||||
if (min == max) {
|
if (min == max) {
|
||||||
return min;
|
return min;
|
||||||
@@ -26,8 +26,8 @@ I FindPossibleMinimum(I min, I max, std::function<O(I)> callback) {
|
|||||||
const I step = ((max - min) / P) + 1;
|
const I step = ((max - min) / P) + 1;
|
||||||
const I offset = step / 2;
|
const I offset = step / 2;
|
||||||
for (uint32_t i = 0; i < P; ++i) {
|
for (uint32_t i = 0; i < P; ++i) {
|
||||||
auto& range = ranges[i];
|
auto& range = ranges.at(i);
|
||||||
range.start = std::min(max, min + i * step);
|
range.start = std::min(max, min + static_cast<int32_t>(i) * step);
|
||||||
range.end = std::min(max, range.start + (step - 1));
|
range.end = std::min(max, range.start + (step - 1));
|
||||||
range.testpoint = range.start + offset;
|
range.testpoint = range.start + offset;
|
||||||
}
|
}
|
||||||
|
|||||||
6
piraw.h
6
piraw.h
@@ -124,8 +124,8 @@ constexpr Color<C> PiRaw<X, Y, C, D, A, P>::CombineRaw(uint32_t y0x0, uint32_t y
|
|||||||
static_assert(C == 3);
|
static_assert(C == 3);
|
||||||
|
|
||||||
Color<C> ret;
|
Color<C> ret;
|
||||||
ret.at(0) = y1x1;
|
ret.at(0) = static_cast<int32_t>(y1x1);
|
||||||
ret.at(1) = (y0x1 + y1x0) / 2;
|
ret.at(1) = static_cast<int32_t>((y0x1 + y1x0) / 2);
|
||||||
ret.at(2) = y0x0;
|
ret.at(2) = static_cast<int32_t>(y0x0);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user