diff --git a/array.h b/array.h new file mode 100644 index 0000000..22d0b02 --- /dev/null +++ b/array.h @@ -0,0 +1,44 @@ +#pragma once + +#include +#include + +template +struct Array : std::array { + using reference = typename std::array::reference; + using const_reference = typename std::array::const_reference; + using size_type = typename std::array::size_type; + + constexpr int32_t ssize() const; + + constexpr reference at(int32_t pos); + constexpr const_reference at(int32_t pos) const; +}; + +template +constexpr int32_t Array::ssize() const { + auto size = this->size(); + assert(size < INT32_MAX); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wshorten-64-to-32" + return size; +#pragma clang diagnostic pop +} + +template +constexpr typename Array::reference Array::at(int32_t pos) { + assert(pos >= 0); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wshorten-64-to-32" + return std::array::at(static_cast(pos)); +#pragma clang diagnostic pop +} + +template +constexpr typename Array::const_reference Array::at(int32_t pos) const { + assert(pos >= 0); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wshorten-64-to-32" + return std::array::at(static_cast(pos)); +#pragma clang diagnostic pop +} diff --git a/color.h b/color.h index e4d7e16..3aa949b 100644 --- a/color.h +++ b/color.h @@ -1,56 +1,55 @@ #pragma once -#include #include #include #include +#include "array.h" #include "intmath.h" constexpr int32_t kMinColor = 0; constexpr int32_t kMaxColor = UINT16_MAX; -// 32-bit for compiler convenience, but values are 16-bit -template -struct Color : public std::array { - constexpr uint32_t AbsDiff(const Color& other) const; +template +struct Color : public Array { + constexpr int32_t AbsDiff(const Color& other) const; constexpr Color Interpolate(const Color& other, int32_t mul, int32_t div) const; constexpr Color Crop() const; }; struct RgbColor : public Color<3> {}; -template -constexpr uint32_t Color::AbsDiff(const Color& other) const { - uint32_t diff = 0; - for (uint32_t c = 0; c < C; ++c) { - diff += static_cast(::AbsDiff(this->at(c), other.at(c))); +template +constexpr int32_t Color::AbsDiff(const Color& other) const { + int32_t diff = 0; + for (int32_t c = 0; c < C; ++c) { + diff += ::AbsDiff(this->at(c), other.at(c)); } return diff; } -template +template constexpr Color Color::Interpolate(const Color& other, int32_t mul, int32_t div) const { Color ret; - for (uint32_t c = 0; c < C; ++c) { + for (int32_t c = 0; c < C; ++c) { ret.at(c) = ::Interpolate(this->at(c), other.at(c), mul, div); } return ret; } -template +template constexpr Color Color::Crop() const { Color ret; - for (uint32_t c = 0; c < C; ++c) { + for (int32_t c = 0; c < C; ++c) { ret.at(c) = std::max(kMinColor, std::min(kMaxColor, this->at(c))); } return ret; } -template +template std::ostream& operator<<(std::ostream& os, const Color& color) { os << std::hex << std::setfill('0') << "Color("; - for (uint32_t c = 0; c < C; ++c) { + for (int32_t c = 0; c < C; ++c) { os << "0x" << std::setw(4) << color.at(0); if (c < C - 1) { os << ", "; diff --git a/colorchecker.h b/colorchecker.h index e61b3b2..13c2f91 100644 --- a/colorchecker.h +++ b/colorchecker.h @@ -1,9 +1,9 @@ #pragma once -#include #include #include +#include "array.h" #include "color.h" #include "colors.h" #include "coord.h" @@ -14,52 +14,52 @@ // Maximum LUT size that has each point adjacent to at least one ColorChecker color. typedef Lut3d<4, 3, 3> ColorCheckerLut3d; -constexpr std::array kColorCheckerSrgb = {{ - {{{{0x7300, 0x5200, 0x4400}}}}, - {{{{0xc200, 0x9600, 0x8200}}}}, - {{{{0x6200, 0x7a00, 0x9d00}}}}, - {{{{0x5700, 0x6c00, 0x4300}}}}, - {{{{0x8500, 0x8000, 0xb100}}}}, - {{{{0x6700, 0xbd00, 0xaa00}}}}, - {{{{0xd600, 0x7e00, 0x2c00}}}}, - {{{{0x5000, 0x5b00, 0xa600}}}}, - {{{{0xc100, 0x5a00, 0x6300}}}}, - {{{{0x5e00, 0x3c00, 0x6c00}}}}, - {{{{0x9d00, 0xbc00, 0x4000}}}}, - {{{{0xe000, 0xa300, 0x2e00}}}}, - {{{{0x3800, 0x3d00, 0x9600}}}}, - {{{{0x4600, 0x9400, 0x4900}}}}, - {{{{0xaf00, 0x3600, 0x3c00}}}}, - {{{{0xe700, 0xc700, 0x1f00}}}}, - {{{{0xbb00, 0x5600, 0x9500}}}}, - {{{{0x0800, 0x8500, 0xa100}}}}, - {{{{0xf300, 0xf300, 0xf200}}}}, - {{{{0xc800, 0xc800, 0xc800}}}}, - {{{{0xa000, 0xa000, 0xa000}}}}, - {{{{0x7a00, 0x7a00, 0x7900}}}}, - {{{{0x5500, 0x5500, 0x5500}}}}, - {{{{0x3400, 0x3400, 0x3400}}}}, -}}; +constexpr Array kColorCheckerSrgb = {{{ + {{{{{0x7300, 0x5200, 0x4400}}}}}, + {{{{{0xc200, 0x9600, 0x8200}}}}}, + {{{{{0x6200, 0x7a00, 0x9d00}}}}}, + {{{{{0x5700, 0x6c00, 0x4300}}}}}, + {{{{{0x8500, 0x8000, 0xb100}}}}}, + {{{{{0x6700, 0xbd00, 0xaa00}}}}}, + {{{{{0xd600, 0x7e00, 0x2c00}}}}}, + {{{{{0x5000, 0x5b00, 0xa600}}}}}, + {{{{{0xc100, 0x5a00, 0x6300}}}}}, + {{{{{0x5e00, 0x3c00, 0x6c00}}}}}, + {{{{{0x9d00, 0xbc00, 0x4000}}}}}, + {{{{{0xe000, 0xa300, 0x2e00}}}}}, + {{{{{0x3800, 0x3d00, 0x9600}}}}}, + {{{{{0x4600, 0x9400, 0x4900}}}}}, + {{{{{0xaf00, 0x3600, 0x3c00}}}}}, + {{{{{0xe700, 0xc700, 0x1f00}}}}}, + {{{{{0xbb00, 0x5600, 0x9500}}}}}, + {{{{{0x0800, 0x8500, 0xa100}}}}}, + {{{{{0xf300, 0xf300, 0xf200}}}}}, + {{{{{0xc800, 0xc800, 0xc800}}}}}, + {{{{{0xa000, 0xa000, 0xa000}}}}}, + {{{{{0x7a00, 0x7a00, 0x7900}}}}}, + {{{{{0x5500, 0x5500, 0x5500}}}}}, + {{{{{0x3400, 0x3400, 0x3400}}}}}, +}}}; -template -std::array, kColorCheckerSrgb.size()> FindClosest(const Image& image) { +template +Array, kColorCheckerSrgb.size()> FindClosest(const Image& image) { static_assert(C == 3); - std::array, kColorCheckerSrgb.size()> closest; - std::array diff; - diff.fill(UINT32_MAX); + Array, kColorCheckerSrgb.size()> closest; + Array diff; + diff.fill(INT32_MAX); - for (uint32_t y = 0; y < Y; ++y) { + for (int32_t y = 0; y < Y; ++y) { const auto& row = image.at(y); - for (uint32_t x = 0; x < X; ++x) { + for (int32_t x = 0; x < X; ++x) { const auto& pixel = row.at(x); - for (uint32_t cc = 0; cc < kColorCheckerSrgb.size(); ++cc) { + for (int32_t cc = 0; cc < kColorCheckerSrgb.ssize(); ++cc) { auto pixel_diff = pixel.AbsDiff(kColorCheckerSrgb.at(cc)); if (pixel_diff < diff.at(cc)) { diff.at(cc) = pixel_diff; - closest.at(cc) = {{{x, y}}}; + closest.at(cc) = {{{{x, y}}}}; } } } @@ -68,20 +68,20 @@ std::array, kColorCheckerSrgb.size()> FindClosest(const Image& return closest; } -template -uint32_t ScoreImage(const Image& image) { +template +int32_t ScoreImage(const Image& image) { static_assert(C == 3); - std::array diff; - diff.fill(UINT32_MAX); + Array diff; + diff.fill(INT32_MAX); - for (uint32_t y = 0; y < Y; ++y) { + for (int32_t y = 0; y < Y; ++y) { const auto& row = image.at(y); - for (uint32_t x = 0; x < X; ++x) { + for (int32_t x = 0; x < X; ++x) { const auto& pixel = row.at(x); - for (uint32_t cc = 0; cc < kColorCheckerSrgb.size(); ++cc) { + for (int32_t cc = 0; cc < kColorCheckerSrgb.ssize(); ++cc) { auto pixel_diff = pixel.AbsDiff(kColorCheckerSrgb.at(cc)); if (pixel_diff < diff.at(cc)) { diff.at(cc) = pixel_diff; @@ -90,47 +90,47 @@ uint32_t ScoreImage(const Image& image) { } } - return std::accumulate(diff.begin(), diff.end(), UINT32_C(0)); + return std::accumulate(diff.begin(), diff.end(), 0); } -template +template std::unique_ptr> HighlightClosest(const Image& image) { static_assert(C == 3); auto out = std::make_unique>(image); auto closest = FindClosest(*out); - for (uint32_t cc = 0; cc < kColorCheckerSrgb.size(); ++cc) { + for (int32_t cc = 0; cc < kColorCheckerSrgb.ssize(); ++cc) { const auto& coord = closest.at(cc); const auto& color = kColorCheckerSrgb.at(cc); - out->DrawSquare({{{std::max(5U, coord.at(0)) - 5, std::max(5U, coord.at(1)) - 5}}}, kBlack, 10); - out->DrawSquare({{{std::max(6U, coord.at(0)) - 6, std::max(6U, coord.at(1)) - 6}}}, color, 12); - out->DrawSquare({{{std::max(7U, coord.at(0)) - 7, std::max(7U, coord.at(1)) - 7}}}, color, 14); - out->DrawSquare({{{std::max(8U, coord.at(0)) - 8, std::max(8U, coord.at(1)) - 8}}}, color, 16); - out->DrawSquare({{{std::max(9U, coord.at(0)) - 9, std::max(9U, coord.at(1)) - 9}}}, kWhite, 18); + out->DrawSquare({{{{std::max(5, coord.at(0)) - 5, std::max(5, coord.at(1)) - 5}}}}, kBlack, 10); + out->DrawSquare({{{{std::max(6, coord.at(0)) - 6, std::max(6, coord.at(1)) - 6}}}}, color, 12); + out->DrawSquare({{{{std::max(7, coord.at(0)) - 7, std::max(7, coord.at(1)) - 7}}}}, color, 14); + out->DrawSquare({{{{std::max(8, coord.at(0)) - 8, std::max(8, coord.at(1)) - 8}}}}, color, 16); + out->DrawSquare({{{{std::max(9, coord.at(0)) - 9, std::max(9, coord.at(1)) - 9}}}}, kWhite, 18); } return out; } -template -uint32_t OptimizeLut(const Image& image, Lut3d* lut) { +template +int32_t OptimizeLut(const Image& image, Lut3d* lut) { static_assert(C == 3); auto snapshot = *lut; - uint32_t diff = 0; + int32_t diff = 0; - for (uint32_t x = 0; x < LUT_X; ++x) { + for (int32_t x = 0; x < LUT_X; ++x) { auto& rect = lut->at(x); - for (uint32_t y = 0; y < LUT_Y; ++y) { + for (int32_t y = 0; y < LUT_Y; ++y) { auto& row = rect.at(y); - for (uint32_t z = 0; z < LUT_Z; ++z) { + for (int32_t z = 0; z < LUT_Z; ++z) { auto& color = row.at(z); - std::cout << Coord<3>{{{x, y, z}}} << std::endl; + std::cout << Coord<3>{{{{x, y, z}}}} << std::endl; - for (uint32_t c = 0; c < C; ++c) { + for (int32_t c = 0; c < C; ++c) { auto& channel = color.at(c); auto min = FindPossibleMinimum( @@ -144,7 +144,7 @@ uint32_t OptimizeLut(const Image& image, Lut3d " << new_value << " (interpolated from " << min << ")" << std::endl; - diff += static_cast(AbsDiff(channel, new_value)); + diff += AbsDiff(channel, new_value); channel = new_value; } } diff --git a/colors.h b/colors.h index 5d22f86..3c78ee5 100644 --- a/colors.h +++ b/colors.h @@ -2,5 +2,5 @@ #include "color.h" -constexpr RgbColor kBlack = {{{{0x0000, 0x0000, 0x0000}}}}; -constexpr RgbColor kWhite = {{{{0xffff, 0xffff, 0xffff}}}}; +constexpr RgbColor kBlack = {{{{{0x0000, 0x0000, 0x0000}}}}}; +constexpr RgbColor kWhite = {{{{{0xffff, 0xffff, 0xffff}}}}}; diff --git a/coord.h b/coord.h index 8196821..e0b6122 100644 --- a/coord.h +++ b/coord.h @@ -3,13 +3,15 @@ #include #include -template -struct Coord : public std::array {}; +#include "array.h" -template +template +struct Coord : public Array {}; + +template std::ostream& operator<<(std::ostream& os, const Coord& coord) { os << "("; - for (uint32_t d = 0; d < D; ++d) { + for (int32_t d = 0; d < D; ++d) { os << coord.at(d); if (d < D - 1) { os << ", "; diff --git a/image.h b/image.h index 888db41..8614b4f 100644 --- a/image.h +++ b/image.h @@ -5,59 +5,60 @@ #include +#include "array.h" #include "color.h" #include "coord.h" -template -class Image : public std::array, X>, Y> { +template +class Image : public Array, X>, Y> { public: constexpr const Color& GetPixel(const Coord<2>& coord) const; void SetPixel(const Coord<2>& coord, const Color& color); - void DrawXLine(const Coord<2>& start, const Color& color, uint32_t length); - void DrawYLine(const Coord<2>& start, const Color& color, uint32_t length); - void DrawRectangle(const Coord<2>& start, const Color& color, uint32_t x_length, uint32_t y_length); - void DrawSquare(const Coord<2>& start, const Color& color, uint32_t length); + void DrawXLine(const Coord<2>& start, const Color& color, int32_t length); + void DrawYLine(const Coord<2>& start, const Color& color, int32_t length); + void DrawRectangle(const Coord<2>& start, const Color& color, int32_t x_length, int32_t y_length); + void DrawSquare(const Coord<2>& start, const Color& color, int32_t length); std::string ToPng(); }; -template +template constexpr const Color& Image::GetPixel(const Coord<2>& coord) const { return this->at(coord.at(1)).at(coord.at(0)); } -template +template void Image::SetPixel(const Coord<2>& coord, const Color& color) { this->at(coord.at(1)).at(coord.at(0)) = color; } -template -void Image::DrawXLine(const Coord<2>& coord, const Color& color, uint32_t length) { +template +void Image::DrawXLine(const Coord<2>& coord, const Color& color, int32_t length) { auto& row = this->at(coord.at(1)); - for (uint32_t x = coord.at(0); x < std::min(X, coord.at(0) + length); ++x) { + for (int32_t x = coord.at(0); x < std::min(X, coord.at(0) + length); ++x) { row.at(x) = color; } } -template -void Image::DrawYLine(const Coord<2>& coord, const Color& color, uint32_t length) { - for (uint32_t y = coord.at(1); y <= std::min(Y, coord.at(1) + length); ++y) { - SetPixel({{{coord.at(0), y}}}, color); +template +void Image::DrawYLine(const Coord<2>& coord, const Color& color, int32_t length) { + for (int32_t y = coord.at(1); y <= std::min(Y, coord.at(1) + length); ++y) { + SetPixel({{{{coord.at(0), y}}}}, color); } } -template -void Image::DrawRectangle(const Coord<2>& start, const Color& color, uint32_t x_length, uint32_t y_length) { +template +void Image::DrawRectangle(const Coord<2>& start, const Color& color, int32_t x_length, int32_t y_length) { DrawXLine(start, color, x_length); - DrawXLine({{{start.at(0), start.at(1) + y_length}}}, color, x_length); + DrawXLine({{{{start.at(0), start.at(1) + y_length}}}}, color, x_length); DrawYLine(start, color, y_length); - DrawYLine({{{start.at(0) + x_length, start.at(1)}}}, color, y_length); + DrawYLine({{{{start.at(0) + x_length, start.at(1)}}}}, color, y_length); } -template -void Image::DrawSquare(const Coord<2>& start, const Color& color, uint32_t length) { +template +void Image::DrawSquare(const Coord<2>& start, const Color& color, int32_t length) { DrawRectangle(start, color, length, length); } @@ -66,7 +67,7 @@ static inline void WriteCallback(png_structp png_ptr, png_bytep data, png_size_t dest->append(reinterpret_cast(data), length); } -template +template std::string Image::ToPng() { static_assert(C == 3); // PNG only supports RGB @@ -84,11 +85,11 @@ std::string Image::ToPng() { png_write_info(png_ptr, info_ptr); for (auto& row : *this) { - std::array out_row; - for (uint32_t x = 0; x < X; ++x) { - out_row[x * 3 + 0] = htons(static_cast(row[x].at(0))); - out_row[x * 3 + 1] = htons(static_cast(row[x].at(1))); - out_row[x * 3 + 2] = htons(static_cast(row[x].at(2))); + Array out_row; + for (int32_t x = 0; x < X; ++x) { + out_row.at(x * 3 + 0) = htons(static_cast(row.at(x).at(0))); + out_row.at(x * 3 + 1) = htons(static_cast(row.at(x).at(1))); + out_row.at(x * 3 + 2) = htons(static_cast(row.at(x).at(2))); } png_write_row(png_ptr, reinterpret_cast(out_row.data())); } diff --git a/intmath.h b/intmath.h index 921f4f8..2dbdd0d 100644 --- a/intmath.h +++ b/intmath.h @@ -7,5 +7,5 @@ constexpr T AbsDiff(T a, T b) { template constexpr T Interpolate(T val0, T val1, T mul, T div) { - return val0 + ((mul * (val1 - val0)) / div); + return val0 + static_cast((static_cast(mul) * (val1 - val0)) / div); } diff --git a/lut.h b/lut.h index 0a9d223..23bb116 100644 --- a/lut.h +++ b/lut.h @@ -1,45 +1,46 @@ #pragma once +#include "array.h" #include "color.h" #include "coord.h" // Hardcoded to Color<3>, so color dimensions == LUT dimensions -template -class Lut3d : public std::array, X>, Y>, Z> { +template +class Lut3d : public Array, X>, Y>, Z> { public: static Lut3d Identity(); Color<3> MapColor(const Color<3>& in) const; - template + template std::unique_ptr> MapImage(const Image& in) const; private: // Return value is (root_indices, remainders) constexpr static std::pair, Coord<3>> FindRoot(const Color<3>& in); - constexpr static std::pair FindChannelRoot(uint32_t value, uint32_t points); + constexpr static std::pair FindChannelRoot(int32_t value, int32_t points); - constexpr static uint32_t BlockSize(uint32_t points); + constexpr static int32_t BlockSize(int32_t points); }; // Minimum size LUT typedef Lut3d<2, 2, 2> MinimalLut3d; -template +template Lut3d Lut3d::Identity() { Lut3d ret; Color<3> color; - for (uint32_t x = 0; x < X; ++x) { + for (int32_t x = 0; x < X; ++x) { auto& rect = ret.at(x); - color.at(0) = std::min(kMaxColor, static_cast(BlockSize(X) * x)); + color.at(0) = std::min(kMaxColor, BlockSize(X) * x); - for (uint32_t y = 0; y < Y; ++y) { + for (int32_t y = 0; y < Y; ++y) { auto& row = rect.at(y); - color.at(1) = std::min(kMaxColor, static_cast(BlockSize(Y) * y)); + color.at(1) = std::min(kMaxColor, BlockSize(Y) * y); - for (uint32_t z = 0; z < Z; ++z) { - color.at(2) = std::min(kMaxColor, static_cast(BlockSize(Z) * z)); + for (int32_t z = 0; z < Z; ++z) { + color.at(2) = std::min(kMaxColor, BlockSize(Z) * z); row.at(z) = color; } } @@ -48,7 +49,7 @@ Lut3d Lut3d::Identity() { return ret; } -template +template Color<3> Lut3d::MapColor(const Color<3>& in) const { const auto root_rem = FindRoot(in); const auto& root = root_rem.first; @@ -58,41 +59,37 @@ Color<3> Lut3d::MapColor(const Color<3>& in) const { auto inter00 = 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), - static_cast(rem.at(0)), - BlockSize(X)); + rem.at(0), BlockSize(X)); auto inter01 = 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), - static_cast(rem.at(0)), - BlockSize(X)); + rem.at(0), BlockSize(X)); auto inter10 = 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), - static_cast(rem.at(0)), - BlockSize(X)); + rem.at(0), BlockSize(X)); auto inter11 = 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), - static_cast(rem.at(0)), - BlockSize(X)); + rem.at(0), BlockSize(X)); - auto inter0 = inter00.Interpolate(inter10, static_cast(rem.at(1)), BlockSize(Y)); - auto inter1 = inter01.Interpolate(inter11, static_cast(rem.at(1)), BlockSize(Y)); + auto inter0 = inter00.Interpolate(inter10, rem.at(1), BlockSize(Y)); + auto inter1 = inter01.Interpolate(inter11, rem.at(1), BlockSize(Y)); - return inter0.Interpolate(inter1, static_cast(rem.at(2)), BlockSize(Z)).Crop(); + return inter0.Interpolate(inter1, rem.at(2), BlockSize(Z)).Crop(); } -template -template +template +template std::unique_ptr> Lut3d::MapImage(const Image& in) const { auto out = std::make_unique>(); - for (uint32_t y = 0; y < IMG_Y; ++y) { - for (uint32_t x = 0; x < IMG_X; ++x) { - Coord<2> coord = {{{x, y}}}; + for (int32_t y = 0; y < IMG_Y; ++y) { + for (int32_t x = 0; x < IMG_X; ++x) { + Coord<2> coord = {{{{x, y}}}}; out->SetPixel(coord, MapColor(in.GetPixel(coord))); } } @@ -100,27 +97,27 @@ std::unique_ptr> Lut3d::MapImage(const Image +template constexpr std::pair, Coord<3>> Lut3d::FindRoot(const Color<3>& in) { - auto root_x = FindChannelRoot(static_cast(in.at(0)), X); - auto root_y = FindChannelRoot(static_cast(in.at(1)), Y); - auto root_z = FindChannelRoot(static_cast(in.at(2)), Z); + auto root_x = FindChannelRoot(in.at(0), X); + auto root_y = FindChannelRoot(in.at(1), Y); + auto root_z = FindChannelRoot(in.at(2), Z); return { - {{{root_x.first, root_y.first, root_z.first}}}, - {{{root_x.second, root_y.second, root_z.second}}}, + {{{{root_x.first, root_y.first, root_z.first}}}}, + {{{{root_x.second, root_y.second, root_z.second}}}}, }; } -template -constexpr std::pair Lut3d::FindChannelRoot(const uint32_t value, const uint32_t points) { +template +constexpr std::pair Lut3d::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. - uint32_t index = std::min(points - 2, value / BlockSize(points)); + int32_t index = std::min(points - 2, value / BlockSize(points)); return std::make_pair(index, value - (index * BlockSize(points))); } -template -constexpr uint32_t Lut3d::BlockSize(uint32_t points) { +template +constexpr int32_t Lut3d::BlockSize(int32_t points) { return (kMaxColor + 1) / (points - 1); } diff --git a/minimum.h b/minimum.h index eecf6e7..a0cdf0a 100644 --- a/minimum.h +++ b/minimum.h @@ -21,13 +21,13 @@ I FindPossibleMinimum(I min, I max, std::function callback) { return min; } - std::array, P> ranges; + Array, P> ranges; const I step = ((max - min) / P) + 1; const I offset = step / 2; - for (uint32_t i = 0; i < P; ++i) { + for (int32_t i = 0; i < P; ++i) { auto& range = ranges.at(i); - range.start = std::min(max, min + static_cast(i) * step); + range.start = std::min(max, min + i * step); range.end = std::min(max, range.start + (step - 1)); range.testpoint = range.start + offset; } diff --git a/piphoto.cc b/piphoto.cc index bae2b40..9586b8b 100644 --- a/piphoto.cc +++ b/piphoto.cc @@ -11,7 +11,7 @@ int main() { std::cout << "Initial error: " << ScoreImage(*image) << std::endl; auto lut = MinimalLut3d::Identity(); - uint32_t diff = 1; + int32_t diff = 1; while (diff) { diff = OptimizeLut<4>(*image, &lut); std::cout << "diff=" << diff << " error=" << ScoreImage(*lut.MapImage(*image)) << std::endl; diff --git a/piraw.h b/piraw.h index dd494c8..aa3a353 100644 --- a/piraw.h +++ b/piraw.h @@ -10,7 +10,7 @@ namespace std { using string_view = experimental::string_view; } -template +template class PiRaw { public: PiRaw() = delete; @@ -21,36 +21,36 @@ class PiRaw { static std::unique_ptr> FromRaw(const std::string_view& raw); private: - static constexpr uint32_t kJpegHeaderBytes = 32768; + static constexpr int32_t kJpegHeaderBytes = 32768; static constexpr const char* kJpegHeaderMagic = "BRCM"; - static constexpr uint32_t kPixelsPerChunk = 4; - static constexpr uint32_t kBitsPerByte = 8; + static constexpr int32_t kPixelsPerChunk = 4; + static constexpr int32_t kBitsPerByte = 8; - static constexpr uint32_t GetRawBytes(); - static constexpr uint32_t GetRowBytes(); - static constexpr uint32_t GetNumRows(); - static constexpr uint32_t GetChunkBytes(); + static constexpr int32_t GetRawBytes(); + static constexpr int32_t GetRowBytes(); + static constexpr int32_t GetNumRows(); + static constexpr int32_t GetChunkBytes(); - static constexpr uint32_t Align(uint32_t val); + static constexpr int32_t Align(int32_t val); - typedef std::array Chunk; + typedef Array Chunk; - static constexpr Chunk GetChunk(const std::string_view& raw, const uint32_t x_chunk, const uint32_t y); - static constexpr Color CombineRaw(uint32_t y0x0, uint32_t y0x1, uint32_t y1x0, uint32_t y1x1); + static constexpr Chunk GetChunk(const std::string_view& raw, const int32_t x_chunk, const int32_t y); + static constexpr Color CombineRaw(int32_t y0x0, int32_t y0x1, int32_t y1x0, int32_t y1x1); }; typedef PiRaw<3280, 2464, 3, 10, 16, 2> PiRaw2; -template +template typename std::unique_ptr> PiRaw::FromJpeg(const std::string_view& jpeg) { static_assert(C == 3); - auto container_len = GetRawBytes() + kJpegHeaderBytes; + size_t container_len = GetRawBytes() + kJpegHeaderBytes; assert(jpeg.substr(jpeg.size() - container_len, 4) == kJpegHeaderMagic); return FromRaw(jpeg.substr(jpeg.size() - GetRawBytes(), GetRawBytes())); } -template +template typename std::unique_ptr> PiRaw::FromRaw(const std::string_view& raw) { static_assert(C == 3); static_assert(X % 2 == 0); @@ -61,8 +61,8 @@ typename std::unique_ptr> PiRaw::FromRa auto image = std::make_unique>(); - for (uint32_t y = 0, out_y = 0; y < Y; y += 2, ++out_y) { - for (uint32_t x_chunk = 0, out_x = 0; x_chunk < X / kPixelsPerChunk; ++x_chunk, out_x += kPixelsPerChunk / 2) { + for (int32_t y = 0, out_y = 0; y < Y; y += 2, ++out_y) { + for (int32_t x_chunk = 0, out_x = 0; x_chunk < X / kPixelsPerChunk; ++x_chunk, out_x += kPixelsPerChunk / 2) { auto chunk1 = GetChunk(raw, x_chunk, y + 0); auto chunk2 = GetChunk(raw, x_chunk, y + 1); image->at(out_y).at(out_x + 0) = CombineRaw(chunk1.at(0), chunk1.at(1), chunk2.at(0), chunk2.at(1)); @@ -72,38 +72,38 @@ typename std::unique_ptr> PiRaw::FromRa return image; } -template -constexpr uint32_t PiRaw::GetRawBytes() { +template +constexpr int32_t PiRaw::GetRawBytes() { return GetRowBytes() * GetNumRows(); } -template -constexpr uint32_t PiRaw::GetRowBytes() { +template +constexpr int32_t PiRaw::GetRowBytes() { return Align(Align(X + P) * D / kBitsPerByte); } -template -constexpr uint32_t PiRaw::GetNumRows() { +template +constexpr int32_t PiRaw::GetNumRows() { return Align(Y + P); } -template -constexpr uint32_t PiRaw::GetChunkBytes() { +template +constexpr int32_t PiRaw::GetChunkBytes() { return D * kPixelsPerChunk / kBitsPerByte; } -template -constexpr uint32_t PiRaw::Align(uint32_t val) { +template +constexpr int32_t PiRaw::Align(int32_t val) { return (~(A - 1)) & ((val) + (A - 1)); } -template -constexpr typename PiRaw::Chunk PiRaw::GetChunk(const std::string_view& raw, const uint32_t x_chunk, const uint32_t y) { +template +constexpr typename PiRaw::Chunk PiRaw::GetChunk(const std::string_view& raw, const int32_t x_chunk, const int32_t y) { // Function is bit depth & layout specific static_assert(C == 3); static_assert(D == 10); - uint32_t start = y * GetRowBytes() + x_chunk * GetChunkBytes(); + size_t start = static_cast(y * GetRowBytes() + x_chunk * GetChunkBytes()); uint32_t high0 = static_cast(raw.at(start + 0)); uint32_t high1 = static_cast(raw.at(start + 1)); uint32_t high2 = static_cast(raw.at(start + 2)); @@ -111,15 +111,15 @@ constexpr typename PiRaw::Chunk PiRaw::GetCh uint32_t packed_low = static_cast(raw.at(start + 4)); Chunk ret; - ret.at(0) = ((high0 << 2) | ((packed_low >> 6) & 0b11)) << 6; - ret.at(1) = ((high1 << 2) | ((packed_low >> 4) & 0b11)) << 6; - ret.at(2) = ((high2 << 2) | ((packed_low >> 2) & 0b11)) << 6; - ret.at(3) = ((high3 << 2) | ((packed_low >> 0) & 0b11)) << 6; + ret.at(0) = static_cast(((high0 << 2) | ((packed_low >> 6) & 0b11)) << 6); + ret.at(1) = static_cast(((high1 << 2) | ((packed_low >> 4) & 0b11)) << 6); + ret.at(2) = static_cast(((high2 << 2) | ((packed_low >> 2) & 0b11)) << 6); + ret.at(3) = static_cast(((high3 << 2) | ((packed_low >> 0) & 0b11)) << 6); return ret; } -template -constexpr Color PiRaw::CombineRaw(uint32_t y0x0, uint32_t y0x1, uint32_t y1x0, uint32_t y1x1) { +template +constexpr Color PiRaw::CombineRaw(int32_t y0x0, int32_t y0x1, int32_t y1x0, int32_t y1x1) { // Function is bit layout specific static_assert(C == 3);