From 100c44fe4ee22fb19cd341a34534098b74ce5bf9 Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Mon, 7 Aug 2017 06:15:20 +0000 Subject: [PATCH] Working identity LUT --- Makefile | 2 +- color.cc | 13 +++++++++++++ color.h | 3 +++ colorchecker.h | 3 +++ image.h | 2 +- lut.h | 52 ++++++++++++++++++++++++++++++++++++++++++++++---- piphoto.cc | 20 +++++++++++-------- 7 files changed, 81 insertions(+), 14 deletions(-) create mode 100644 color.cc diff --git a/Makefile b/Makefile index 418e223..546a24c 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ all: piphoto -objects = piphoto.o coord.o util.o +objects = piphoto.o color.o coord.o util.o piphoto: $(objects) Makefile clang-3.9 -O3 -g -Weverything -Werror -Wno-c++98-compat -Wno-c++98-c++11-compat-pedantic --std=c++1z --stdlib=libc++ -o piphoto $(objects) -lc++ -lunwind -lpng diff --git a/color.cc b/color.cc new file mode 100644 index 0000000..e47de3b --- /dev/null +++ b/color.cc @@ -0,0 +1,13 @@ +#include "color.h" + +#include + +std::ostream& operator<<(std::ostream& os, const Color& color) { + return os + << std::hex << std::setfill('0') + << "rgb(" + << "0x" << std::setw(4) << color.r << ", " + << "0x" << std::setw(4) << color.g << ", " + << "0x" << std::setw(4) << color.b + << ")" << std::dec; +} diff --git a/color.h b/color.h index ffac6c1..e085a67 100644 --- a/color.h +++ b/color.h @@ -1,6 +1,7 @@ #pragma once #include +#include constexpr uint32_t kNumColors = (1 << 16); @@ -20,3 +21,5 @@ constexpr uint32_t Color::Difference(const Color& other) const { ((b > other.b) ? (b - other.b) : (other.b - b)) ); } + +std::ostream& operator<<(std::ostream& os, const Color& color); diff --git a/colorchecker.h b/colorchecker.h index cffe702..9a1052c 100644 --- a/colorchecker.h +++ b/colorchecker.h @@ -5,6 +5,9 @@ #include "color.h" #include "coord.h" #include "image.h" +#include "lut.h" + +typedef Lut3d<4, 3, 3> ColorCheckerLut3d; constexpr std::array kColorCheckerSrgb = {{ {0x7300, 0x5200, 0x4400}, diff --git a/image.h b/image.h index 9059079..7e958fa 100644 --- a/image.h +++ b/image.h @@ -61,7 +61,7 @@ void Image::DrawSquare(const Coord& start, const Color& color, uint32_t le DrawRectangle(start, color, length, length); } -static void WriteCallback(png_structp png_ptr, png_bytep data, png_size_t length) { +static inline void WriteCallback(png_structp png_ptr, png_bytep data, png_size_t length) { auto dest = static_cast(png_get_io_ptr(png_ptr)); dest->append(reinterpret_cast(data), length); } diff --git a/lut.h b/lut.h index 63adf1d..c2c37ba 100644 --- a/lut.h +++ b/lut.h @@ -11,8 +11,13 @@ struct Coord3d { template class Lut3d : public std::array, G>, R> { public: + static std::unique_ptr> Identity(); + Color MapColor(const Color& in) const; + template + std::unique_ptr> MapImage(const Image& in) const; + private: constexpr static Color InterpolateColor(const Color& i0, const Color& i1, uint32_t mul, uint32_t div); constexpr static uint32_t Interpolate(uint32_t i0, uint32_t i1, uint32_t mul, uint32_t div); @@ -24,6 +29,29 @@ class Lut3d : public std::array, G>, R> { constexpr static uint32_t BlockSize(uint32_t points); }; +template +std::unique_ptr> Lut3d::Identity() { + auto ret = std::make_unique>(); + + Color color; + for (uint32_t r = 0; r < R; ++r) { + auto& rect = ret->at(r); + color.r = std::min(kNumColors - 1, BlockSize(R) * r); + + for (uint32_t g = 0; g < G; ++g) { + auto& row = rect.at(g); + color.g = std::min(kNumColors - 1, BlockSize(G) * g); + + for (uint32_t b = 0; b < B; ++b) { + color.b = std::min(kNumColors - 1, BlockSize(B) * b); + row.at(b) = color; + } + } + } + + return ret; +} + template Color Lut3d::MapColor(const Color& in) const { const auto root_rem = FindRoot(in); @@ -61,6 +89,21 @@ Color Lut3d::MapColor(const Color& in) const { return InterpolateColor(inter0, inter1, rem.b, BlockSize(B)); } +template +template +std::unique_ptr> Lut3d::MapImage(const Image& in) const { + auto out = std::make_unique>(); + + for (uint32_t y = 0; y < Y; ++y) { + for (uint32_t x = 0; x < X; ++x) { + Coord coord = {x, y}; + out->SetPixel(coord, MapColor(in.GetPixel(coord))); + } + } + + return out; +} + template constexpr Color Lut3d::InterpolateColor(const Color& i0, const Color& i1, uint32_t mul, uint32_t div) { return { @@ -72,14 +115,15 @@ constexpr Color Lut3d::InterpolateColor(const Color& i0, const Color& i template constexpr uint32_t Lut3d::Interpolate(uint32_t i0, uint32_t i1, uint32_t mul, uint32_t div) { - return i0 + ((mul * i1) / div); + assert(i1 >= i0); + return i0 + ((mul * (i1 - i0)) / div); } template constexpr std::pair Lut3d::FindRoot(const Color& in) { auto root_r = FindChannelRoot(in.r, R); - auto root_g = FindChannelRoot(in.r, G); - auto root_b = FindChannelRoot(in.r, B); + auto root_g = FindChannelRoot(in.g, G); + auto root_b = FindChannelRoot(in.b, B); return { {root_r.first, root_g.first, root_b.first}, {root_r.second, root_g.second, root_b.second}, @@ -95,6 +139,6 @@ constexpr std::pair Lut3d::FindChannelRoot(const ui } template -constexpr uint32_t BlockSize(uint32_t points) { +constexpr uint32_t Lut3d::BlockSize(uint32_t points) { return kNumColors / (points - 1); } diff --git a/piphoto.cc b/piphoto.cc index ae3fbab..4491c86 100644 --- a/piphoto.cc +++ b/piphoto.cc @@ -11,16 +11,20 @@ int main() { auto image = PiRaw2::FromJpeg(ReadFile("test.jpg")); - auto closest = ColorCheckerClosest(*image); + + auto lut = ColorCheckerLut3d::Identity(); + auto image2 = lut->MapImage(*image); + + auto closest = ColorCheckerClosest(*image2); for (uint32_t cc = 0; cc < kColorCheckerSrgb.size(); ++cc) { const auto& coord = closest.at(cc); const auto& color = kColorCheckerSrgb.at(cc); - std::cout << cc << ": " << coord << " difference=" << color.Difference(image->GetPixel(coord)) << std::endl; - image->DrawSquare({std::max(5U, coord.x) - 5, std::max(5U, coord.y) - 5}, kBlack, 10); - image->DrawSquare({std::max(6U, coord.x) - 6, std::max(6U, coord.y) - 6}, color, 12); - image->DrawSquare({std::max(7U, coord.x) - 7, std::max(7U, coord.y) - 7}, color, 14); - image->DrawSquare({std::max(8U, coord.x) - 8, std::max(8U, coord.y) - 8}, color, 16); - image->DrawSquare({std::max(9U, coord.x) - 9, std::max(9U, coord.y) - 9}, kWhite, 18); + std::cout << cc << ": " << coord << " difference=" << color.Difference(image2->GetPixel(coord)) << std::endl; + image2->DrawSquare({std::max(5U, coord.x) - 5, std::max(5U, coord.y) - 5}, kBlack, 10); + image2->DrawSquare({std::max(6U, coord.x) - 6, std::max(6U, coord.y) - 6}, color, 12); + image2->DrawSquare({std::max(7U, coord.x) - 7, std::max(7U, coord.y) - 7}, color, 14); + image2->DrawSquare({std::max(8U, coord.x) - 8, std::max(8U, coord.y) - 8}, color, 16); + image2->DrawSquare({std::max(9U, coord.x) - 9, std::max(9U, coord.y) - 9}, kWhite, 18); } - WriteFile("test.png", image->ToPng()); + WriteFile("test.png", image2->ToPng()); }