Skip to content

Commit

Permalink
Refactor color_range to use color_t
Browse files Browse the repository at this point in the history
Temporarily breaks TC/RC coloring, will fix.
  • Loading branch information
Vultraz committed Dec 1, 2016
1 parent 49155fa commit f2ab245
Show file tree
Hide file tree
Showing 20 changed files with 285 additions and 287 deletions.
2 changes: 1 addition & 1 deletion src/ai/formula/function_table.cpp
Expand Up @@ -1235,7 +1235,7 @@ class debug_label_function : public function_expression {
display* gui = display::get_singleton();
std::string team_name;

color_t color = color_t::from_argb_bytes(team::get_side_rgb(ai_.get_side()));
color_t color = team::get_side_rgb(ai_.get_side());

const terrain_label *res;
res = gui->labels().set_label(location, text, ai_.get_side() - 1, team_name, color);
Expand Down
186 changes: 71 additions & 115 deletions src/color_range.cpp
Expand Up @@ -26,146 +26,102 @@
#include "util.hpp"

#include <iomanip>
#include <unordered_set>

std::map<uint32_t, uint32_t> recolor_range(const color_range& new_range, const std::vector<uint32_t>& old_rgb){
std::map<uint32_t, uint32_t> map_rgb;
color_range_map recolor_range(const color_range& new_range, const std::vector<color_t>& old_rgb)
{
color_range_map map_rgb;

const uint16_t new_red = new_range.mid().r;
const uint16_t new_green = new_range.mid().g;
const uint16_t new_blue = new_range.mid().b;

const uint16_t max_red = new_range.max().r;
const uint16_t max_green = new_range.max().g;
const uint16_t max_blue = new_range.max().b;

uint16_t new_red = (new_range.mid() & 0x00FF0000)>>16;
uint16_t new_green= (new_range.mid() & 0x0000FF00)>>8;
uint16_t new_blue = (new_range.mid() & 0x000000FF);
uint16_t max_red = (new_range.max() & 0x00FF0000)>>16;
uint16_t max_green= (new_range.max() & 0x0000FF00)>>8 ;
uint16_t max_blue = (new_range.max() & 0x000000FF) ;
uint16_t min_red = (new_range.min() & 0x00FF0000)>>16;
uint16_t min_green= (new_range.min() & 0x0000FF00)>>8 ;
uint16_t min_blue = (new_range.min() & 0x000000FF) ;
const uint16_t min_red = new_range.min().r;
const uint16_t min_green = new_range.min().g;
const uint16_t min_blue = new_range.min().b;

// Map first color in vector to exact new color
uint32_t temp_rgb= old_rgb.empty() ? 0 : old_rgb[0];
uint16_t old_r=(temp_rgb & 0X00FF0000)>>16;
uint16_t old_g=(temp_rgb & 0X0000FF00)>>8;
uint16_t old_b=(temp_rgb & 0X000000FF);
uint16_t reference_avg = (( old_r + old_g + old_b) / 3);

for(std::vector< uint32_t >::const_iterator temp_rgb2 = old_rgb.begin();
temp_rgb2 != old_rgb.end(); ++temp_rgb2)
{
old_r=((*temp_rgb2) & 0X00FF0000)>>16;
old_g=((*temp_rgb2) & 0X0000FF00)>>8;
old_b=((*temp_rgb2) & 0X000000FF);

const uint16_t old_avg = (( old_r + old_g + old_b) / 3);
// Calculate new color
uint32_t new_r, new_g, new_b;

if(reference_avg && old_avg <= reference_avg){
float old_rat = static_cast<float>(old_avg)/reference_avg;
new_r=uint32_t( old_rat * new_red + (1 - old_rat) * min_red);
new_g=uint32_t( old_rat * new_green + (1 - old_rat) * min_green);
new_b=uint32_t( old_rat * new_blue + (1 - old_rat) * min_blue);
}else if(255 - reference_avg){
float old_rat = (255.0f - static_cast<float>(old_avg)) /
(255.0f - reference_avg);

new_r=static_cast<uint32_t>( old_rat * new_red + (1 - old_rat) * max_red);
new_g=static_cast<uint32_t>( old_rat * new_green + (1 - old_rat) * max_green);
new_b=static_cast<uint32_t>( old_rat * new_blue + (1 - old_rat) * max_blue);
}else{
new_r=0; new_g=0; new_b=0; // Suppress warning
assert(false);
const color_t temp_rgb = old_rgb.empty() ? color_t() : old_rgb[0];

const uint16_t reference_avg = (temp_rgb.r + temp_rgb.g + temp_rgb.b) / 3;

for(const auto& old_c : old_rgb) {
const uint16_t old_avg = (old_c.r + old_c.g + old_c.b) / 3;

// Calculate new color
uint32_t new_r = 0, new_g = 0, new_b = 0;

if(reference_avg && old_avg <= reference_avg) {
float old_ratio = static_cast<float>(old_avg) / reference_avg;

new_r = static_cast<uint32_t>(old_ratio * new_red + (1 - old_ratio) * min_red);
new_g = static_cast<uint32_t>(old_ratio * new_green + (1 - old_ratio) * min_green);
new_b = static_cast<uint32_t>(old_ratio * new_blue + (1 - old_ratio) * min_blue);
} else if(reference_avg != 255) {
float old_ratio = (255.0f - static_cast<float>(old_avg)) / (255.0f - reference_avg);

new_r = static_cast<uint32_t>(old_ratio * new_red + (1 - old_ratio) * max_red);
new_g = static_cast<uint32_t>(old_ratio * new_green + (1 - old_ratio) * max_green);
new_b = static_cast<uint32_t>(old_ratio * new_blue + (1 - old_ratio) * max_blue);
} else {
// Should never get here.
// Would imply old_avg > reference_avg = 255
}
assert(false);
}

if(new_r>255) new_r=255;
if(new_g>255) new_g=255;
if(new_b>255) new_b=255;
new_r = std::min<uint32_t>(new_r, 255);
new_g = std::min<uint32_t>(new_g, 255);
new_b = std::min<uint32_t>(new_b, 255);

uint32_t newrgb = (new_r << 16) + (new_g << 8) + (new_b );
map_rgb[*temp_rgb2]=newrgb;
map_rgb[old_c] = {static_cast<uint8_t>(new_r), static_cast<uint8_t>(new_g), static_cast<uint8_t>(new_b)};
}

return map_rgb;
}

bool string2rgb(const std::string& s, std::vector<uint32_t>& result) {
result = std::vector<uint32_t>();
std::vector<uint32_t> out;
std::vector<std::string> rgb_vec = utils::split(s);
std::vector<std::string>::iterator c=rgb_vec.begin();
while(c!=rgb_vec.end())
{
uint32_t rgb_hex;
if(c->length() != 6)
{
try {
// integer triplets, e.g. white="255,255,255"
rgb_hex = (0x00FF0000 & (std::stoi(*c++))<<16); //red
if(c!=rgb_vec.end())
{
rgb_hex += (0x0000FF00 & (std::stoi(*c++)<<8)); //green
if(c!=rgb_vec.end())
{
rgb_hex += (0x000000FF & (std::stoi(*c++)<<0)); //blue
}
}
} catch (std::invalid_argument&) {
return false;
}
} else {
// hexadecimal format, e.g. white="FFFFFF"
char* endptr;
rgb_hex = (0x00FFFFFF & strtol(c->c_str(), &endptr, 16));
if (*endptr != '\0') {
return false;
}
++c;
}
out.push_back(rgb_hex);
}
result = out;
return true;
}
std::vector<color_t> palette(const color_range& cr)
{
std::vector<color_t> temp, res;
std::unordered_set<color_t> clist;

std::vector<uint32_t> palette(color_range cr){
// generate a color palette from a color range
std::vector<uint32_t> temp,res;
std::set<uint32_t> clist;
// use blue to make master set of possible colors
for(int i=255;i!=0;i--){
int j=255-i;
uint32_t rgb = i;
temp.push_back(rgb);
rgb = (j << 16) + (j << 8) + 255;
temp.push_back(rgb);
// Use blue to make master set of possible colors
for(int i = 255; i != 0; i--) {
const int j = 255 - i;

temp.emplace_back(0,0,i);
temp.emplace_back(j,j,255);
}

// Use recolor function to generate list of possible colors.
// Could use a special function, would be more efficient,
// but harder to maintain.
std::map<uint32_t,uint32_t> cmap = recolor_range(cr,temp);
for(std::map<uint32_t,uint32_t>::const_iterator k=cmap.begin(); k!=cmap.end();++k){
clist.insert(k->second);
// Could use a special function, would be more efficient, but harder to maintain.
color_range_map cmap = recolor_range(cr, temp);
for(const auto& cm : cmap) {
clist.insert(cm.second);
}
res.push_back(cmap[255]);
for(std::set<uint32_t>::const_iterator c=clist.begin();c!=clist.end();++c){
if(*c != res[0] && *c!=0 && *c != 0x00FFFFFF){
res.push_back(*c);}

res.push_back(cmap[{0,0,255}]);

for(const auto& cs : clist) {
if(cs != res[0] && !cs.null() && cs != color_t(255, 255, 255)) {
res.push_back(cs);
}
}
return(res);

return res;
}

std::string color_range::debug() const
{
std::ostringstream o;

static const uint32_t mask = 0x00FFFFFF;

o << std::hex << std::setfill('0')
<< '{' << std::setw(6) << (mid_ & mask)
<< ',' << std::setw(6) << (max_ & mask)
<< ',' << std::setw(6) << (min_ & mask)
<< ',' << std::setw(6) << (rep_ & mask)
o << '{' << mid_.to_hex_string()
<< ',' << max_.to_hex_string()
<< ',' << min_.to_hex_string()
<< ',' << rep_.to_hex_string()
<< '}';

return o.str();
Expand Down

0 comments on commit f2ab245

Please sign in to comment.