I've been using a color matching algorithm I created based on the information here:
Nearest color algorithm using Hex Triplet - Software Engineering Stack Exchange[
^]
The trouble is, it's not quite giving me all the information I think.
I need to compare two - say RGB pixels
So like
constexpr double difference(type rhs) const {
return helpers::pixel_diff_impl<type,0,ChannelTraits...>::diff_sum(*this,rhs);
}
The goofy diff_sum() calls just add the squared value of each channel difference together. so like (lhs[R]-rhs[R])
2+(lhs[G]-rhs[G])
2+(lhs[B]-rhs[B])
2
This isn't yielding what I want. It works on my 7-color e-paper display for the most part, properly matching red, blue, yellow and green so far, but is stuck on orange. Orange is not matching and I can't figure out why. It comes up as red.
I also have some accompanying code that uses the difference code. I've put it in what I have tried.
Disclaimer: I realize some of this code may take explaining. The trouble is I'm not sure which parts need the most explanation. It's too familiar to me, if that makes sense. Leave comments with your questions, and I'll do my best to answer them.
What I have tried:
Here are a couple of templates I use to get difference values.
The first one will basically do (R-R2)
2+(G-G2)
2+(B-B2)
2
The last one will basically do (R
2+G
2+B
2)-(R2
2+G2
2+B2
2)
I DO NOT USE the last one. It was one I was simply trying.
template<typename PixelType,int Count,typename... ChannelTraits>
struct pixel_diff_impl;
template<typename PixelType,int Count, typename ChannelTrait,typename... ChannelTraits>
struct pixel_diff_impl<PixelType,Count,ChannelTrait,ChannelTraits...> {
using ch = typename PixelType::template channel_by_index<Count>;
using next = pixel_diff_impl<PixelType,Count+1, ChannelTraits...>;
constexpr static inline double diff_sum(PixelType lhs,PixelType rhs) {
constexpr const size_t index = Count;
if(ChannelTrait::bit_depth==0) return NAN;
const double d = (lhs.template channelr<index>()-rhs.template channelr<index>());
return d*d+next::diff_sum(lhs,rhs);
}
};
template<typename PixelType,int Count>
struct pixel_diff_impl<PixelType,Count> {
constexpr static inline double diff_sum(PixelType lhs,PixelType rhs) {
return 0.0;
}
};
template<typename PixelType,int Count,typename... ChannelTraits>
struct pixel_sumsqr_impl;
template<typename PixelType,int Count, typename ChannelTrait,typename... ChannelTraits>
struct pixel_sumsqr_impl<PixelType,Count,ChannelTrait,ChannelTraits...> {
using ch = typename PixelType::template channel_by_index<Count>;
using next = pixel_sumsqr_impl<PixelType,Count+1, ChannelTraits...>;
constexpr static inline double sumsqr(PixelType lhs) {
constexpr const size_t index = Count;
if(ChannelTrait::bit_depth==0) return NAN;
const double d = lhs.template channel<index>();
return d*d+next::sumsqr(lhs);
}
};
template<typename PixelType,int Count>
struct pixel_sumsqr_impl<PixelType,Count> {
constexpr static inline double sumsqr(PixelType lhs) {
return 0.0;
}
};
Here's the difference code:
constexpr double difference(type rhs) const {
return helpers::pixel_diff_impl<type,0,ChannelTraits...>::diff_sum(*this,rhs);
}
Here's the code that uses difference.
template<typename PixelType>
struct waveshare5in65_palette {
private:
constexpr static gfx::gfx_result index_to_mapped(int idx,PixelType* result) {
switch(idx) {
case 0:
return gfx::convert(gfx::rgb_pixel<16>(0,0,0),result);
case 1:
return gfx::convert(gfx::rgb_pixel<16>(31,63,31),result);
case 2:
return gfx::convert(gfx::rgb_pixel<16>(0,63,0),result);
case 3:
return gfx::convert(gfx::rgb_pixel<16>(0,0,31),result);
case 4:
return gfx::convert(gfx::rgb_pixel<16>(31,0,0),result);
case 5:
return gfx::convert(gfx::rgb_pixel<16>(31,63,0),result);
default: return gfx::convert(gfx::rgb_pixel<16>(31,31,0),result);
}
}
public:
using type = waveshare5in65_palette;
using pixel_type = gfx::pixel<gfx::channel_traits<gfx::channel_name::index,4,0,6>>;
using mapped_pixel_type = PixelType;
constexpr static const bool writable = false;
constexpr static const size_t size = 6;
gfx::gfx_result map(pixel_type pixel,mapped_pixel_type* mapped_pixel) const {
return index_to_mapped(pixel.channel<gfx::channel_name::index>(),mapped_pixel);
}
gfx::gfx_result nearest(mapped_pixel_type mapped_pixel,pixel_type* pixel) const {
if(nullptr==pixel) {
return gfx::gfx_result::invalid_argument;
}
mapped_pixel_type mpx;
gfx::gfx_result r = index_to_mapped(0,&mpx);
if(gfx::gfx_result::success!=r) {
return r;
}
double least = mpx.difference(mapped_pixel);
if(0.0==least) {
pixel->native_value = 0;
return gfx::gfx_result::success;
}
int ii=0;
for(int i = 1;i<size;++i) {
r=index_to_mapped(i,&mpx);
if(gfx::gfx_result::success!=r) {
return r;
}
double cmp = mpx.difference(mapped_pixel);
if(0.0==cmp) {
ii=i;
least = 0.0;
break;
}
if(cmp<least) {
least = cmp;
ii=i;
}
}
pixel->channel<gfx::channel_name::index>(ii);
return gfx::gfx_result::success;
}
};