Working identity LUT
This commit is contained in:
2
Makefile
2
Makefile
@@ -1,6 +1,6 @@
|
|||||||
all: piphoto
|
all: piphoto
|
||||||
|
|
||||||
objects = piphoto.o coord.o util.o
|
objects = piphoto.o color.o coord.o util.o
|
||||||
|
|
||||||
piphoto: $(objects) Makefile
|
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
|
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
|
||||||
|
|||||||
13
color.cc
Normal file
13
color.cc
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#include "color.h"
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
3
color.h
3
color.h
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
constexpr uint32_t kNumColors = (1 << 16);
|
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))
|
((b > other.b) ? (b - other.b) : (other.b - b))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, const Color& color);
|
||||||
|
|||||||
@@ -5,6 +5,9 @@
|
|||||||
#include "color.h"
|
#include "color.h"
|
||||||
#include "coord.h"
|
#include "coord.h"
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
|
#include "lut.h"
|
||||||
|
|
||||||
|
typedef Lut3d<4, 3, 3> ColorCheckerLut3d;
|
||||||
|
|
||||||
constexpr std::array<Color, 24> kColorCheckerSrgb = {{
|
constexpr std::array<Color, 24> kColorCheckerSrgb = {{
|
||||||
{0x7300, 0x5200, 0x4400},
|
{0x7300, 0x5200, 0x4400},
|
||||||
|
|||||||
2
image.h
2
image.h
@@ -61,7 +61,7 @@ void Image<X, Y>::DrawSquare(const Coord& start, const Color& color, uint32_t le
|
|||||||
DrawRectangle(start, color, length, length);
|
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<std::string*>(png_get_io_ptr(png_ptr));
|
auto dest = static_cast<std::string*>(png_get_io_ptr(png_ptr));
|
||||||
dest->append(reinterpret_cast<char*>(data), length);
|
dest->append(reinterpret_cast<char*>(data), length);
|
||||||
}
|
}
|
||||||
|
|||||||
52
lut.h
52
lut.h
@@ -11,8 +11,13 @@ struct Coord3d {
|
|||||||
template <uint32_t R, uint32_t G, uint32_t B>
|
template <uint32_t R, uint32_t G, uint32_t B>
|
||||||
class Lut3d : public std::array<std::array<std::array<Color, B>, G>, R> {
|
class Lut3d : public std::array<std::array<std::array<Color, B>, G>, R> {
|
||||||
public:
|
public:
|
||||||
|
static std::unique_ptr<Lut3d<R, G, B>> Identity();
|
||||||
|
|
||||||
Color MapColor(const Color& in) const;
|
Color MapColor(const Color& in) const;
|
||||||
|
|
||||||
|
template <uint32_t X, uint32_t Y>
|
||||||
|
std::unique_ptr<Image<X, Y>> MapImage(const Image<X, Y>& in) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
constexpr static Color InterpolateColor(const Color& i0, const Color& i1, uint32_t mul, uint32_t div);
|
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);
|
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<std::array<std::array<Color, B>, G>, R> {
|
|||||||
constexpr static uint32_t BlockSize(uint32_t points);
|
constexpr static uint32_t BlockSize(uint32_t points);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <uint32_t R, uint32_t G, uint32_t B>
|
||||||
|
std::unique_ptr<Lut3d<R, G, B>> Lut3d<R, G, B>::Identity() {
|
||||||
|
auto ret = std::make_unique<Lut3d<R, G, B>>();
|
||||||
|
|
||||||
|
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 <uint32_t R, uint32_t G, uint32_t B>
|
template <uint32_t R, uint32_t G, uint32_t B>
|
||||||
Color Lut3d<R, G, B>::MapColor(const Color& in) const {
|
Color Lut3d<R, G, B>::MapColor(const Color& in) const {
|
||||||
const auto root_rem = FindRoot(in);
|
const auto root_rem = FindRoot(in);
|
||||||
@@ -61,6 +89,21 @@ Color Lut3d<R, G, B>::MapColor(const Color& in) const {
|
|||||||
return InterpolateColor(inter0, inter1, rem.b, BlockSize(B));
|
return InterpolateColor(inter0, inter1, rem.b, BlockSize(B));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <uint32_t R, uint32_t G, uint32_t B>
|
||||||
|
template <uint32_t X, uint32_t Y>
|
||||||
|
std::unique_ptr<Image<X, Y>> Lut3d<R, G, B>::MapImage(const Image<X, Y>& in) const {
|
||||||
|
auto out = std::make_unique<Image<X, Y>>();
|
||||||
|
|
||||||
|
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 <uint32_t R, uint32_t G, uint32_t B>
|
template <uint32_t R, uint32_t G, uint32_t B>
|
||||||
constexpr Color Lut3d<R, G, B>::InterpolateColor(const Color& i0, const Color& i1, uint32_t mul, uint32_t div) {
|
constexpr Color Lut3d<R, G, B>::InterpolateColor(const Color& i0, const Color& i1, uint32_t mul, uint32_t div) {
|
||||||
return {
|
return {
|
||||||
@@ -72,14 +115,15 @@ constexpr Color Lut3d<R, G, B>::InterpolateColor(const Color& i0, const Color& i
|
|||||||
|
|
||||||
template <uint32_t R, uint32_t G, uint32_t B>
|
template <uint32_t R, uint32_t G, uint32_t B>
|
||||||
constexpr uint32_t Lut3d<R, G, B>::Interpolate(uint32_t i0, uint32_t i1, uint32_t mul, uint32_t div) {
|
constexpr uint32_t Lut3d<R, G, B>::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 <uint32_t R, uint32_t G, uint32_t B>
|
template <uint32_t R, uint32_t G, uint32_t B>
|
||||||
constexpr std::pair<Coord3d, Coord3d> Lut3d<R, G, B>::FindRoot(const Color& in) {
|
constexpr std::pair<Coord3d, Coord3d> Lut3d<R, G, B>::FindRoot(const Color& in) {
|
||||||
auto root_r = FindChannelRoot(in.r, R);
|
auto root_r = FindChannelRoot(in.r, R);
|
||||||
auto root_g = FindChannelRoot(in.r, G);
|
auto root_g = FindChannelRoot(in.g, G);
|
||||||
auto root_b = FindChannelRoot(in.r, B);
|
auto root_b = FindChannelRoot(in.b, B);
|
||||||
return {
|
return {
|
||||||
{root_r.first, root_g.first, root_b.first},
|
{root_r.first, root_g.first, root_b.first},
|
||||||
{root_r.second, root_g.second, root_b.second},
|
{root_r.second, root_g.second, root_b.second},
|
||||||
@@ -95,6 +139,6 @@ constexpr std::pair<uint32_t, uint32_t> Lut3d<R, G, B>::FindChannelRoot(const ui
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <uint32_t R, uint32_t G, uint32_t B>
|
template <uint32_t R, uint32_t G, uint32_t B>
|
||||||
constexpr uint32_t BlockSize(uint32_t points) {
|
constexpr uint32_t Lut3d<R, G, B>::BlockSize(uint32_t points) {
|
||||||
return kNumColors / (points - 1);
|
return kNumColors / (points - 1);
|
||||||
}
|
}
|
||||||
|
|||||||
20
piphoto.cc
20
piphoto.cc
@@ -11,16 +11,20 @@
|
|||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
auto image = PiRaw2::FromJpeg(ReadFile("test.jpg"));
|
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) {
|
for (uint32_t cc = 0; cc < kColorCheckerSrgb.size(); ++cc) {
|
||||||
const auto& coord = closest.at(cc);
|
const auto& coord = closest.at(cc);
|
||||||
const auto& color = kColorCheckerSrgb.at(cc);
|
const auto& color = kColorCheckerSrgb.at(cc);
|
||||||
std::cout << cc << ": " << coord << " difference=" << color.Difference(image->GetPixel(coord)) << std::endl;
|
std::cout << cc << ": " << coord << " difference=" << color.Difference(image2->GetPixel(coord)) << std::endl;
|
||||||
image->DrawSquare({std::max(5U, coord.x) - 5, std::max(5U, coord.y) - 5}, kBlack, 10);
|
image2->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);
|
image2->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);
|
image2->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);
|
image2->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);
|
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());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user