Better color typing
This commit is contained in:
2
Makefile
2
Makefile
@@ -1,6 +1,6 @@
|
|||||||
all: piphoto
|
all: piphoto
|
||||||
|
|
||||||
objects = piphoto.o lut.o util.o
|
objects = piphoto.o color.o lut.o util.o
|
||||||
|
|
||||||
piphoto: $(objects) Makefile
|
piphoto: $(objects) Makefile
|
||||||
clang-3.9 -O3 -g -Weverything -Werror --std=c++1z --stdlib=libc++ -o piphoto $(objects) -lc++ -lunwind -lpng
|
clang-3.9 -O3 -g -Weverything -Werror --std=c++1z --stdlib=libc++ -o piphoto $(objects) -lc++ -lunwind -lpng
|
||||||
|
|||||||
4
color.cc
Normal file
4
color.cc
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#include "color.h"
|
||||||
|
|
||||||
|
RgbColor::RgbColor(const Color<3>& src)
|
||||||
|
: Color<3>(src) {}
|
||||||
12
color.h
12
color.h
@@ -10,14 +10,22 @@
|
|||||||
constexpr int32_t kMinColor = 0;
|
constexpr int32_t kMinColor = 0;
|
||||||
constexpr int32_t kMaxColor = UINT16_MAX;
|
constexpr int32_t kMaxColor = UINT16_MAX;
|
||||||
|
|
||||||
|
class ColorBase {};
|
||||||
|
|
||||||
template <int32_t C>
|
template <int32_t C>
|
||||||
struct Color : public Array<int32_t, C> {
|
struct Color : public Array<int32_t, C>, public ColorBase {
|
||||||
constexpr int32_t AbsDiff(const Color<C>& other) const;
|
constexpr int32_t AbsDiff(const Color<C>& other) const;
|
||||||
constexpr Color<C> Interpolate(const Color<C>& other, int32_t mul, int32_t div) const;
|
constexpr Color<C> Interpolate(const Color<C>& other, int32_t mul, int32_t div) const;
|
||||||
constexpr Color<C> Crop() const;
|
constexpr Color<C> Crop() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RgbColor : public Color<3> {};
|
|
||||||
|
struct RgbColor : public Color<3> {
|
||||||
|
public:
|
||||||
|
RgbColor() = default;
|
||||||
|
RgbColor(const Color<3>& src);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
template <int32_t C>
|
template <int32_t C>
|
||||||
constexpr int32_t Color<C>::AbsDiff(const Color<C>& other) const {
|
constexpr int32_t Color<C>::AbsDiff(const Color<C>& other) const {
|
||||||
|
|||||||
@@ -14,7 +14,9 @@
|
|||||||
// Maximum LUT size that has each point adjacent to at least one ColorChecker color.
|
// Maximum LUT size that has each point adjacent to at least one ColorChecker color.
|
||||||
typedef Lut3d<4, 3, 3> ColorCheckerLut3d;
|
typedef Lut3d<4, 3, 3> ColorCheckerLut3d;
|
||||||
|
|
||||||
constexpr Array<RgbColor, 24> kColorCheckerSrgb = {{{
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wglobal-constructors"
|
||||||
|
const Array<RgbColor, 24> kColorCheckerSrgb = {{{
|
||||||
{{{{{0x7300, 0x5200, 0x4400}}}}},
|
{{{{{0x7300, 0x5200, 0x4400}}}}},
|
||||||
{{{{{0xc200, 0x9600, 0x8200}}}}},
|
{{{{{0xc200, 0x9600, 0x8200}}}}},
|
||||||
{{{{{0x6200, 0x7a00, 0x9d00}}}}},
|
{{{{{0x6200, 0x7a00, 0x9d00}}}}},
|
||||||
@@ -40,11 +42,10 @@ constexpr Array<RgbColor, 24> kColorCheckerSrgb = {{{
|
|||||||
{{{{{0x5500, 0x5500, 0x5500}}}}},
|
{{{{{0x5500, 0x5500, 0x5500}}}}},
|
||||||
{{{{{0x3400, 0x3400, 0x3400}}}}},
|
{{{{{0x3400, 0x3400, 0x3400}}}}},
|
||||||
}}};
|
}}};
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
template <int32_t X, int32_t Y, int32_t C>
|
template <int32_t X, int32_t Y>
|
||||||
Array<Coord<2>, kColorCheckerSrgb.size()> FindClosest(const Image<X, Y, C>& image) {
|
Array<Coord<2>, kColorCheckerSrgb.size()> FindClosest(const Image<X, Y, RgbColor>& image) {
|
||||||
static_assert(C == 3);
|
|
||||||
|
|
||||||
Array<Coord<2>, kColorCheckerSrgb.size()> closest;
|
Array<Coord<2>, kColorCheckerSrgb.size()> closest;
|
||||||
Array<int32_t, kColorCheckerSrgb.size()> diff;
|
Array<int32_t, kColorCheckerSrgb.size()> diff;
|
||||||
diff.fill(INT32_MAX);
|
diff.fill(INT32_MAX);
|
||||||
@@ -68,10 +69,8 @@ Array<Coord<2>, kColorCheckerSrgb.size()> FindClosest(const Image<X, Y, C>& imag
|
|||||||
return closest;
|
return closest;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int32_t X, int32_t Y, int32_t C>
|
template <int32_t X, int32_t Y>
|
||||||
int32_t ScoreLut(const Image<X, Y, C>& image, const LutBase& lut) {
|
int32_t ScoreLut(const Image<X, Y, RgbColor>& image, const LutBase& lut) {
|
||||||
static_assert(C == 3);
|
|
||||||
|
|
||||||
Array<int32_t, kColorCheckerSrgb.size()> diff;
|
Array<int32_t, kColorCheckerSrgb.size()> diff;
|
||||||
diff.fill(INT32_MAX);
|
diff.fill(INT32_MAX);
|
||||||
|
|
||||||
@@ -93,11 +92,9 @@ int32_t ScoreLut(const Image<X, Y, C>& image, const LutBase& lut) {
|
|||||||
return std::accumulate(diff.begin(), diff.end(), 0);
|
return std::accumulate(diff.begin(), diff.end(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int32_t X, int32_t Y, int32_t C>
|
template <int32_t X, int32_t Y>
|
||||||
std::unique_ptr<Image<X, Y, C>> HighlightClosest(const Image<X, Y, C>& image) {
|
std::unique_ptr<Image<X, Y, RgbColor>> HighlightClosest(const Image<X, Y, RgbColor>& image) {
|
||||||
static_assert(C == 3);
|
auto out = std::make_unique<Image<X, Y, RgbColor>>(image);
|
||||||
|
|
||||||
auto out = std::make_unique<Image<X, Y, C>>(image);
|
|
||||||
|
|
||||||
auto closest = FindClosest(*out);
|
auto closest = FindClosest(*out);
|
||||||
for (int32_t cc = 0; cc < kColorCheckerSrgb.ssize(); ++cc) {
|
for (int32_t cc = 0; cc < kColorCheckerSrgb.ssize(); ++cc) {
|
||||||
@@ -112,10 +109,8 @@ std::unique_ptr<Image<X, Y, C>> HighlightClosest(const Image<X, Y, C>& image) {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int32_t LUT_X, int32_t LUT_Y, int32_t LUT_Z, int32_t IMG_X, int32_t IMG_Y, int32_t C>
|
template <int32_t LUT_X, int32_t LUT_Y, int32_t LUT_Z, int32_t IMG_X, int32_t IMG_Y>
|
||||||
int32_t OptimizeLut(const Image<IMG_X, IMG_Y, C>& image, Lut3d<LUT_X, LUT_Y, LUT_Z>* lut) {
|
int32_t OptimizeLut(const Image<IMG_X, IMG_Y, RgbColor>& image, Lut3d<LUT_X, LUT_Y, LUT_Z>* lut) {
|
||||||
static_assert(C == 3);
|
|
||||||
|
|
||||||
auto snapshot = *lut;
|
auto snapshot = *lut;
|
||||||
int32_t diff = 0;
|
int32_t diff = 0;
|
||||||
|
|
||||||
@@ -130,7 +125,7 @@ int32_t OptimizeLut(const Image<IMG_X, IMG_Y, C>& image, Lut3d<LUT_X, LUT_Y, LUT
|
|||||||
|
|
||||||
std::cout << Coord<3>{{{{x, y, z}}}} << std::endl;
|
std::cout << Coord<3>{{{{x, y, z}}}} << std::endl;
|
||||||
|
|
||||||
for (int32_t c = 0; c < C; ++c) {
|
for (int32_t c = 0; c < color.size(); ++c) {
|
||||||
auto& channel = color.at(c);
|
auto& channel = color.at(c);
|
||||||
|
|
||||||
auto min = FindPossibleMinimum<int32_t, int32_t, 8>(
|
auto min = FindPossibleMinimum<int32_t, int32_t, 8>(
|
||||||
@@ -154,10 +149,8 @@ int32_t OptimizeLut(const Image<IMG_X, IMG_Y, C>& image, Lut3d<LUT_X, LUT_Y, LUT
|
|||||||
return diff;
|
return diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int32_t LUT_X, int32_t IMG_X, int32_t IMG_Y, int32_t C>
|
template <int32_t LUT_X, int32_t IMG_X, int32_t IMG_Y>
|
||||||
int32_t OptimizeLut(const Image<IMG_X, IMG_Y, C>& image, Lut1d<LUT_X>* lut) {
|
int32_t OptimizeLut(const Image<IMG_X, IMG_Y, RgbColor>& image, Lut1d<LUT_X>* lut) {
|
||||||
static_assert(C == 3);
|
|
||||||
|
|
||||||
auto snapshot = *lut;
|
auto snapshot = *lut;
|
||||||
int32_t diff = 0;
|
int32_t diff = 0;
|
||||||
|
|
||||||
@@ -166,7 +159,7 @@ int32_t OptimizeLut(const Image<IMG_X, IMG_Y, C>& image, Lut1d<LUT_X>* lut) {
|
|||||||
|
|
||||||
std::cout << Coord<1>{{{{x}}}} << std::endl;
|
std::cout << Coord<1>{{{{x}}}} << std::endl;
|
||||||
|
|
||||||
for (int32_t c = 0; c < C; ++c) {
|
for (int32_t c = 0; c < color.ssize(); ++c) {
|
||||||
auto& channel = color.at(c);
|
auto& channel = color.at(c);
|
||||||
|
|
||||||
auto min = FindPossibleMinimum<int32_t, int32_t, 8>(
|
auto min = FindPossibleMinimum<int32_t, int32_t, 8>(
|
||||||
|
|||||||
7
colors.h
7
colors.h
@@ -2,5 +2,8 @@
|
|||||||
|
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
|
|
||||||
constexpr RgbColor kBlack = {{{{{0x0000, 0x0000, 0x0000}}}}};
|
#pragma clang diagnostic push
|
||||||
constexpr RgbColor kWhite = {{{{{0xffff, 0xffff, 0xffff}}}}};
|
#pragma clang diagnostic ignored "-Wglobal-constructors"
|
||||||
|
const RgbColor kBlack = {{{{{0x0000, 0x0000, 0x0000}}}}};
|
||||||
|
const RgbColor kWhite = {{{{{0xffff, 0xffff, 0xffff}}}}};
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|||||||
44
image.h
44
image.h
@@ -9,57 +9,57 @@
|
|||||||
#include "color.h"
|
#include "color.h"
|
||||||
#include "coord.h"
|
#include "coord.h"
|
||||||
|
|
||||||
template <int32_t X, int32_t Y, int32_t C>
|
template <int32_t X, int32_t Y, class C>
|
||||||
class Image : public Array<Array<Color<C>, X>, Y> {
|
class Image : public Array<Array<C, X>, Y> {
|
||||||
public:
|
public:
|
||||||
constexpr const Color<C>& GetPixel(const Coord<2>& coord) const;
|
constexpr const C& GetPixel(const Coord<2>& coord) const;
|
||||||
|
|
||||||
void SetPixel(const Coord<2>& coord, const Color<C>& color);
|
void SetPixel(const Coord<2>& coord, const C& color);
|
||||||
void DrawXLine(const Coord<2>& start, const Color<C>& color, int32_t length);
|
void DrawXLine(const Coord<2>& start, const C& color, int32_t length);
|
||||||
void DrawYLine(const Coord<2>& start, const Color<C>& color, int32_t length);
|
void DrawYLine(const Coord<2>& start, const C& color, int32_t length);
|
||||||
void DrawRectangle(const Coord<2>& start, const Color<C>& color, int32_t x_length, int32_t y_length);
|
void DrawRectangle(const Coord<2>& start, const C& color, int32_t x_length, int32_t y_length);
|
||||||
void DrawSquare(const Coord<2>& start, const Color<C>& color, int32_t length);
|
void DrawSquare(const Coord<2>& start, const C& color, int32_t length);
|
||||||
|
|
||||||
std::string ToPng();
|
std::string ToPng();
|
||||||
};
|
};
|
||||||
|
|
||||||
template <int32_t X, int32_t Y, int32_t C>
|
template <int32_t X, int32_t Y, class C>
|
||||||
constexpr const Color<C>& Image<X, Y, C>::GetPixel(const Coord<2>& coord) const {
|
constexpr const C& Image<X, Y, C>::GetPixel(const Coord<2>& coord) const {
|
||||||
return this->at(coord.at(1)).at(coord.at(0));
|
return this->at(coord.at(1)).at(coord.at(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int32_t X, int32_t Y, int32_t C>
|
template <int32_t X, int32_t Y, class C>
|
||||||
void Image<X, Y, C>::SetPixel(const Coord<2>& coord, const Color<C>& color) {
|
void Image<X, Y, C>::SetPixel(const Coord<2>& coord, const C& color) {
|
||||||
if (coord.at(0) >= X || coord.at(1) >= Y) {
|
if (coord.at(0) >= X || coord.at(1) >= Y) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this->at(coord.at(1)).at(coord.at(0)) = color;
|
this->at(coord.at(1)).at(coord.at(0)) = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int32_t X, int32_t Y, int32_t C>
|
template <int32_t X, int32_t Y, class C>
|
||||||
void Image<X, Y, C>::DrawXLine(const Coord<2>& coord, const Color<C>& color, int32_t length) {
|
void Image<X, Y, C>::DrawXLine(const Coord<2>& coord, const C& color, int32_t length) {
|
||||||
for (int32_t x = coord.at(0); x <= coord.at(0) + length; ++x) {
|
for (int32_t x = coord.at(0); x <= coord.at(0) + length; ++x) {
|
||||||
SetPixel({{{{x, coord.at(1)}}}}, color);
|
SetPixel({{{{x, coord.at(1)}}}}, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int32_t X, int32_t Y, int32_t C>
|
template <int32_t X, int32_t Y, class C>
|
||||||
void Image<X, Y, C>::DrawYLine(const Coord<2>& coord, const Color<C>& color, int32_t length) {
|
void Image<X, Y, C>::DrawYLine(const Coord<2>& coord, const C& color, int32_t length) {
|
||||||
for (int32_t y = coord.at(1); y <= coord.at(1) + length; ++y) {
|
for (int32_t y = coord.at(1); y <= coord.at(1) + length; ++y) {
|
||||||
SetPixel({{{{coord.at(0), y}}}}, color);
|
SetPixel({{{{coord.at(0), y}}}}, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int32_t X, int32_t Y, int32_t C>
|
template <int32_t X, int32_t Y, class C>
|
||||||
void Image<X, Y, C>::DrawRectangle(const Coord<2>& start, const Color<C>& color, int32_t x_length, int32_t y_length) {
|
void Image<X, Y, C>::DrawRectangle(const Coord<2>& start, const C& color, int32_t x_length, int32_t y_length) {
|
||||||
DrawXLine(start, color, x_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, 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 <int32_t X, int32_t Y, int32_t C>
|
template <int32_t X, int32_t Y, class C>
|
||||||
void Image<X, Y, C>::DrawSquare(const Coord<2>& start, const Color<C>& color, int32_t length) {
|
void Image<X, Y, C>::DrawSquare(const Coord<2>& start, const C& color, int32_t length) {
|
||||||
DrawRectangle(start, color, length, length);
|
DrawRectangle(start, color, length, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,9 +68,9 @@ static inline void WriteCallback(png_structp png_ptr, png_bytep data, png_size_t
|
|||||||
dest->append(reinterpret_cast<char*>(data), length);
|
dest->append(reinterpret_cast<char*>(data), length);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int32_t X, int32_t Y, int32_t C>
|
template <int32_t X, int32_t Y, class C>
|
||||||
std::string Image<X, Y, C>::ToPng() {
|
std::string Image<X, Y, C>::ToPng() {
|
||||||
static_assert(C == 3); // PNG only supports RGB
|
// TODO: specialize this to RgbColor
|
||||||
|
|
||||||
std::string ret;
|
std::string ret;
|
||||||
|
|
||||||
|
|||||||
5
lut.h
5
lut.h
@@ -11,9 +11,10 @@ class LutBase {
|
|||||||
LutBase(const LutBase&) = default;
|
LutBase(const LutBase&) = default;
|
||||||
virtual ~LutBase();
|
virtual ~LutBase();
|
||||||
|
|
||||||
|
// TODO: Allow other color dimensions
|
||||||
virtual Color<3> MapColor(const Color<3>& in) const = 0;
|
virtual Color<3> MapColor(const Color<3>& in) const = 0;
|
||||||
|
|
||||||
template <int32_t X, int32_t Y, int32_t C>
|
template <int32_t X, int32_t Y, class C>
|
||||||
std::unique_ptr<Image<X, Y, C>> MapImage(const Image<X, Y, C>& in) const;
|
std::unique_ptr<Image<X, Y, C>> MapImage(const Image<X, Y, C>& in) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -21,7 +22,7 @@ class LutBase {
|
|||||||
static constexpr int32_t BlockSize(int32_t points);
|
static constexpr int32_t BlockSize(int32_t points);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <int32_t X, int32_t Y, int32_t C>
|
template <int32_t X, int32_t Y, class C>
|
||||||
std::unique_ptr<Image<X, Y, C>> LutBase::MapImage(const Image<X, Y, C>& in) const {
|
std::unique_ptr<Image<X, Y, C>> LutBase::MapImage(const Image<X, Y, C>& in) const {
|
||||||
auto out = std::make_unique<Image<X, Y, C>>();
|
auto out = std::make_unique<Image<X, Y, C>>();
|
||||||
|
|
||||||
|
|||||||
57
piraw.h
57
piraw.h
@@ -10,15 +10,15 @@ namespace std {
|
|||||||
using string_view = experimental::string_view;
|
using string_view = experimental::string_view;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int32_t X, int32_t Y, int32_t C, int32_t D, int32_t A, int32_t P>
|
template <int32_t X, int32_t Y, int32_t D, int32_t A, int32_t P>
|
||||||
class PiRaw {
|
class PiRaw {
|
||||||
public:
|
public:
|
||||||
PiRaw() = delete;
|
PiRaw() = delete;
|
||||||
PiRaw(const PiRaw&) = delete;
|
PiRaw(const PiRaw&) = delete;
|
||||||
PiRaw(PiRaw&&) = delete;
|
PiRaw(PiRaw&&) = delete;
|
||||||
|
|
||||||
static std::unique_ptr<Image<X / 2, Y / 2, C>> FromJpeg(const std::string_view& jpeg);
|
static std::unique_ptr<Image<X / 2, Y / 2, RgbColor>> FromJpeg(const std::string_view& jpeg);
|
||||||
static std::unique_ptr<Image<X / 2, Y / 2, C>> FromRaw(const std::string_view& raw);
|
static std::unique_ptr<Image<X / 2, Y / 2, RgbColor>> FromRaw(const std::string_view& raw);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr int32_t kJpegHeaderBytes = 32768;
|
static constexpr int32_t kJpegHeaderBytes = 32768;
|
||||||
@@ -36,30 +36,27 @@ class PiRaw {
|
|||||||
typedef Array<int32_t, kPixelsPerChunk> Chunk;
|
typedef Array<int32_t, kPixelsPerChunk> Chunk;
|
||||||
|
|
||||||
static constexpr Chunk GetChunk(const std::string_view& raw, const int32_t x_chunk, const int32_t y);
|
static constexpr Chunk GetChunk(const std::string_view& raw, const int32_t x_chunk, const int32_t y);
|
||||||
static constexpr Color<C> CombineRaw(int32_t y0x0, int32_t y0x1, int32_t y1x0, int32_t y1x1);
|
static constexpr RgbColor CombineRaw(int32_t y0x0, int32_t y0x1, int32_t y1x0, int32_t y1x1);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef PiRaw<3280, 2464, 3, 10, 16, 2> PiRaw2;
|
typedef PiRaw<3280, 2464, 10, 16, 2> PiRaw2;
|
||||||
|
|
||||||
template <int32_t X, int32_t Y, int32_t C, int32_t D, int32_t A, int32_t P>
|
|
||||||
typename std::unique_ptr<Image<X / 2, Y / 2, C>> PiRaw<X, Y, C, D, A, P>::FromJpeg(const std::string_view& jpeg) {
|
|
||||||
static_assert(C == 3);
|
|
||||||
|
|
||||||
|
template <int32_t X, int32_t Y, int32_t D, int32_t A, int32_t P>
|
||||||
|
typename std::unique_ptr<Image<X / 2, Y / 2, RgbColor>> PiRaw<X, Y, D, A, P>::FromJpeg(const std::string_view& jpeg) {
|
||||||
size_t container_len = GetRawBytes() + kJpegHeaderBytes;
|
size_t container_len = GetRawBytes() + kJpegHeaderBytes;
|
||||||
assert(jpeg.substr(jpeg.size() - container_len, 4) == kJpegHeaderMagic);
|
assert(jpeg.substr(jpeg.size() - container_len, 4) == kJpegHeaderMagic);
|
||||||
return FromRaw(jpeg.substr(jpeg.size() - GetRawBytes(), GetRawBytes()));
|
return FromRaw(jpeg.substr(jpeg.size() - GetRawBytes(), GetRawBytes()));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int32_t X, int32_t Y, int32_t C, int32_t D, int32_t A, int32_t P>
|
template <int32_t X, int32_t Y, int32_t D, int32_t A, int32_t P>
|
||||||
typename std::unique_ptr<Image<X / 2, Y / 2, C>> PiRaw<X, Y, C, D, A, P>::FromRaw(const std::string_view& raw) {
|
typename std::unique_ptr<Image<X / 2, Y / 2, RgbColor>> PiRaw<X, Y, D, A, P>::FromRaw(const std::string_view& raw) {
|
||||||
static_assert(C == 3);
|
|
||||||
static_assert(X % 2 == 0);
|
static_assert(X % 2 == 0);
|
||||||
static_assert(Y % 2 == 0);
|
static_assert(Y % 2 == 0);
|
||||||
static_assert(kPixelsPerChunk == 4);
|
static_assert(kPixelsPerChunk == 4);
|
||||||
|
|
||||||
assert(raw.size() == GetRawBytes());
|
assert(raw.size() == GetRawBytes());
|
||||||
|
|
||||||
auto image = std::make_unique<Image<X / 2, Y / 2, C>>();
|
auto image = std::make_unique<Image<X / 2, Y / 2, RgbColor>>();
|
||||||
|
|
||||||
for (int32_t y = 0, out_y = 0; y < Y; y += 2, ++out_y) {
|
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) {
|
for (int32_t x_chunk = 0, out_x = 0; x_chunk < X / kPixelsPerChunk; ++x_chunk, out_x += kPixelsPerChunk / 2) {
|
||||||
@@ -72,35 +69,34 @@ typename std::unique_ptr<Image<X / 2, Y / 2, C>> PiRaw<X, Y, C, D, A, P>::FromRa
|
|||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int32_t X, int32_t Y, int32_t C, int32_t D, int32_t A, int32_t P>
|
template <int32_t X, int32_t Y, int32_t D, int32_t A, int32_t P>
|
||||||
constexpr int32_t PiRaw<X, Y, C, D, A, P>::GetRawBytes() {
|
constexpr int32_t PiRaw<X, Y, D, A, P>::GetRawBytes() {
|
||||||
return GetRowBytes() * GetNumRows();
|
return GetRowBytes() * GetNumRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int32_t X, int32_t Y, int32_t C, int32_t D, int32_t A, int32_t P>
|
template <int32_t X, int32_t Y, int32_t D, int32_t A, int32_t P>
|
||||||
constexpr int32_t PiRaw<X, Y, C, D, A, P>::GetRowBytes() {
|
constexpr int32_t PiRaw<X, Y, D, A, P>::GetRowBytes() {
|
||||||
return Align(Align(X + P) * D / kBitsPerByte);
|
return Align(Align(X + P) * D / kBitsPerByte);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int32_t X, int32_t Y, int32_t C, int32_t D, int32_t A, int32_t P>
|
template <int32_t X, int32_t Y, int32_t D, int32_t A, int32_t P>
|
||||||
constexpr int32_t PiRaw<X, Y, C, D, A, P>::GetNumRows() {
|
constexpr int32_t PiRaw<X, Y, D, A, P>::GetNumRows() {
|
||||||
return Align(Y + P);
|
return Align(Y + P);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int32_t X, int32_t Y, int32_t C, int32_t D, int32_t A, int32_t P>
|
template <int32_t X, int32_t Y, int32_t D, int32_t A, int32_t P>
|
||||||
constexpr int32_t PiRaw<X, Y, C, D, A, P>::GetChunkBytes() {
|
constexpr int32_t PiRaw<X, Y, D, A, P>::GetChunkBytes() {
|
||||||
return D * kPixelsPerChunk / kBitsPerByte;
|
return D * kPixelsPerChunk / kBitsPerByte;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int32_t X, int32_t Y, int32_t C, int32_t D, int32_t A, int32_t P>
|
template <int32_t X, int32_t Y, int32_t D, int32_t A, int32_t P>
|
||||||
constexpr int32_t PiRaw<X, Y, C, D, A, P>::Align(int32_t val) {
|
constexpr int32_t PiRaw<X, Y, D, A, P>::Align(int32_t val) {
|
||||||
return (~(A - 1)) & ((val) + (A - 1));
|
return (~(A - 1)) & ((val) + (A - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int32_t X, int32_t Y, int32_t C, int32_t D, int32_t A, int32_t P>
|
template <int32_t X, int32_t Y, int32_t D, int32_t A, int32_t P>
|
||||||
constexpr typename PiRaw<X, Y, C, D, A, P>::Chunk PiRaw<X, Y, C, D, A, P>::GetChunk(const std::string_view& raw, const int32_t x_chunk, const int32_t y) {
|
constexpr typename PiRaw<X, Y, D, A, P>::Chunk PiRaw<X, Y, D, A, P>::GetChunk(const std::string_view& raw, const int32_t x_chunk, const int32_t y) {
|
||||||
// Function is bit depth & layout specific
|
// Function is bit depth & layout specific
|
||||||
static_assert(C == 3);
|
|
||||||
static_assert(D == 10);
|
static_assert(D == 10);
|
||||||
|
|
||||||
size_t start = static_cast<size_t>(y * GetRowBytes() + x_chunk * GetChunkBytes());
|
size_t start = static_cast<size_t>(y * GetRowBytes() + x_chunk * GetChunkBytes());
|
||||||
@@ -118,12 +114,9 @@ constexpr typename PiRaw<X, Y, C, D, A, P>::Chunk PiRaw<X, Y, C, D, A, P>::GetCh
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int32_t X, int32_t Y, int32_t C, int32_t D, int32_t A, int32_t P>
|
template <int32_t X, int32_t Y, int32_t D, int32_t A, int32_t P>
|
||||||
constexpr Color<C> PiRaw<X, Y, C, D, A, P>::CombineRaw(int32_t y0x0, int32_t y0x1, int32_t y1x0, int32_t y1x1) {
|
constexpr RgbColor PiRaw<X, Y, D, A, P>::CombineRaw(int32_t y0x0, int32_t y0x1, int32_t y1x0, int32_t y1x1) {
|
||||||
// Function is bit layout specific
|
RgbColor ret;
|
||||||
static_assert(C == 3);
|
|
||||||
|
|
||||||
Color<C> ret;
|
|
||||||
ret.at(0) = static_cast<int32_t>(y1x1);
|
ret.at(0) = static_cast<int32_t>(y1x1);
|
||||||
ret.at(1) = static_cast<int32_t>((y0x1 + y1x0) / 2);
|
ret.at(1) = static_cast<int32_t>((y0x1 + y1x0) / 2);
|
||||||
ret.at(2) = static_cast<int32_t>(y0x0);
|
ret.at(2) = static_cast<int32_t>(y0x0);
|
||||||
|
|||||||
Reference in New Issue
Block a user