color_range.cpp

Go to the documentation of this file.
00001 /* $Id: color_range.cpp 26449 2008-05-07 17:57:47Z mordante $ */
00002 /*
00003    Copyright (C) 2003 - 2008 by David White <dave@whitevine.net>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License version 2
00008    or at your option any later version.
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY.
00011 
00012    See the COPYING file for more details.
00013 */
00014 
00015 //! @file color_range.cpp
00016 //! Generate ranges of colors, and color palettes.
00017 //! Used e.g. to color HP, XP.
00018 
00019 #include "game_config.hpp"
00020 #include "global.hpp"
00021 #include "color_range.hpp"
00022 #include "map.hpp"
00023 #include "serialization/string_utils.hpp"
00024 
00025 #include <cassert>
00026 #include <set>
00027 #include <string>
00028 #include <cstring>
00029 #include <vector>
00030 
00031 std::map<Uint32, Uint32> recolor_range(const color_range& new_range, const std::vector<Uint32>& old_rgb){
00032     std::map<Uint32, Uint32> map_rgb;
00033 
00034     Uint16 new_red  = (new_range.mid() & 0x00FF0000)>>16;
00035     Uint16 new_green= (new_range.mid() & 0x0000FF00)>>8;
00036     Uint16 new_blue = (new_range.mid() & 0x000000FF);
00037     Uint16 max_red  = (new_range.max() & 0x00FF0000)>>16;
00038     Uint16 max_green= (new_range.max() & 0x0000FF00)>>8 ;
00039     Uint16 max_blue = (new_range.max() & 0x000000FF)    ;
00040     Uint16 min_red  = (new_range.min() & 0x00FF0000)>>16;
00041     Uint16 min_green= (new_range.min() & 0x0000FF00)>>8 ;
00042     Uint16 min_blue = (new_range.min() & 0x000000FF)    ;
00043 
00044     // Map first color in vector to exact new color
00045     Uint32 temp_rgb= old_rgb.empty() ? 0 : old_rgb[0];
00046     Uint16 old_r=(temp_rgb & 0X00FF0000)>>16;
00047     Uint16 old_g=(temp_rgb & 0X0000FF00)>>8;
00048     Uint16 old_b=(temp_rgb & 0X000000FF);
00049     Uint16 reference_avg = (( old_r + old_g + old_b) / 3);
00050 
00051     for(std::vector< Uint32 >::const_iterator temp_rgb2 = old_rgb.begin();
00052           temp_rgb2 != old_rgb.end(); temp_rgb2++)
00053     {
00054         Uint16 old_r=((*temp_rgb2) & 0X00FF0000)>>16;
00055         Uint16 old_g=((*temp_rgb2) & 0X0000FF00)>>8;
00056         Uint16 old_b=((*temp_rgb2) & 0X000000FF);
00057 
00058         const Uint16 old_avg = (( old_r + old_g +  old_b) / 3);
00059          // Calculate new color
00060         Uint32 new_r, new_g, new_b;
00061 
00062         if(reference_avg && old_avg <= reference_avg){
00063             float old_rat = static_cast<float>(old_avg)/reference_avg;
00064             new_r=Uint32( old_rat * new_red   + (1 - old_rat) * min_red);
00065             new_g=Uint32( old_rat * new_green + (1 - old_rat) * min_green);
00066             new_b=Uint32( old_rat * new_blue  + (1 - old_rat) * min_blue);
00067         }else if(255 - reference_avg){
00068             float old_rat = (255.0 - static_cast<float>(old_avg)) /
00069                 (255.0 - reference_avg);
00070 
00071             new_r=static_cast<Uint32>( old_rat * new_red   + (1 - old_rat) * max_red);
00072             new_g=static_cast<Uint32>( old_rat * new_green + (1 - old_rat) * max_green);
00073             new_b=static_cast<Uint32>( old_rat * new_blue  + (1 - old_rat) * max_blue);
00074         }else{
00075             new_r=0; new_g=0; new_b=0; // Suppress warning
00076             assert(false);
00077             // Should never get here.
00078             // Would imply old_avg > reference_avg = 255
00079          }
00080 
00081         if(new_r>255) new_r=255;
00082         if(new_g>255) new_g=255;
00083         if(new_b>255) new_b=255;
00084 
00085         Uint32 newrgb = (new_r << 16) + (new_g << 8) + (new_b );
00086         map_rgb[*temp_rgb2]=newrgb;
00087     }
00088 
00089     return map_rgb;
00090 }
00091 
00092 //! Convert comma separated string into rgb values.
00093 std::vector<Uint32> string2rgb(std::string s){
00094     std::vector<Uint32> out;
00095     std::vector<std::string> rgb_vec = utils::split(s);
00096     std::vector<std::string>::iterator c=rgb_vec.begin();
00097     while(c!=rgb_vec.end())
00098     {
00099         Uint32 rgb_hex;
00100         if(c->length() != 6)
00101         {
00102             // integer triplets, e.g. white="255,255,255"
00103             rgb_hex =  (0x00FF0000 & ((lexical_cast<int>(*c++))<<16)); //red
00104             if(c!=rgb_vec.end())
00105             {
00106                 rgb_hex += (0x0000FF00 & ((lexical_cast<int>(*c++))<<8)); //green
00107                 if(c!=rgb_vec.end())
00108                 {
00109                     rgb_hex += (0x000000FF & ((lexical_cast<int>(*c++))<<0)); //blue
00110                 }
00111             }
00112         } else {
00113             // hexadecimal format, e.g. white="FFFFFF"
00114             char* endptr;
00115             rgb_hex = (0x00FFFFFF & strtol(c->c_str(), &endptr, 16));
00116             if (*endptr != '\0') {
00117                 throw bad_lexical_cast();
00118             }
00119             c++;
00120         }
00121         out.push_back(rgb_hex);
00122     }
00123     return(out);
00124 }
00125 
00126 std::vector<Uint32> palette(color_range cr){
00127 // generate a color palette from a color range
00128     std::vector<Uint32> temp,res;
00129     std::set<Uint32> clist;
00130     // use blue to make master set of possible colors
00131     for(int i=255;i!=0;i--){
00132         int j=255-i;
00133         Uint32 rgb = i;
00134         temp.push_back(rgb);
00135         rgb = (j << 16) + (j << 8) + 255;
00136         temp.push_back(rgb);
00137     }
00138 
00139     // Use recolor function to generate list of possible colors.
00140     // Could use a special function, would be more efficient,
00141     // but harder to maintain.
00142     std::map<Uint32,Uint32> cmap = recolor_range(cr,temp);
00143     for(std::map<Uint32,Uint32>::const_iterator k=cmap.begin(); k!=cmap.end();k++){
00144         clist.insert(k->second);
00145     }
00146     res.push_back(cmap[255]);
00147     for(std::set<Uint32>::const_iterator c=clist.begin();c!=clist.end();c++){
00148         if(*c != res[0] && *c!=0 && *c != 0x00FFFFFF){
00149             res.push_back(*c);}
00150     }
00151     return(res);
00152 }
00153 
00154 std::string rgb2highlight(Uint32 rgb)
00155 {
00156     std::stringstream h("");
00157     // Must match what the escape interpreter for marked-up-text expects
00158     h << "<" << ((rgb & 0xFF0000) >> 16)
00159       << "," << ((rgb & 0x00FF00) >> 8)
00160       << "," << (rgb & 0x0000FF) << ">";
00161     return h.str();
00162 }
00163 
00164 int color_range::index() const
00165 {
00166     for(int i = 1; i <= gamemap::MAX_PLAYERS; ++i) {
00167         if(*this==(game_config::color_info(lexical_cast<std::string>(i)))) {
00168             return i;
00169         }
00170     }
00171     return 0;
00172 }

Generated by doxygen 1.5.5 on 23 May 2008 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs