1 /* === S Y N F I G ========================================================= */
3 ** \brief Template File
8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
10 ** This package is free software; you can redistribute it and/or
11 ** modify it under the terms of the GNU General Public License as
12 ** published by the Free Software Foundation; either version 2 of
13 ** the License, or (at your option) any later version.
15 ** This package is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 ** General Public License for more details.
21 /* ========================================================================= */
23 /* === H E A D E R S ======================================================= */
40 /* === U S I N G =========================================================== */
44 using namespace synfig;
46 /* === M A C R O S ========================================================= */
48 #define PALETTE_FILE_COOKIE "SYNFIGPAL1.0"
50 /* === G L O B A L S ======================================================= */
52 bool weight_less_than(const PaletteItem& lhs,const PaletteItem& rhs)
54 return lhs.weight<rhs.weight;
57 bool luma_less_than(const PaletteItem& lhs,const PaletteItem& rhs)
59 return lhs.color.get_y()<rhs.color.get_y();
62 bool luma_less_than(const PaletteItem& lhs,const float& rhs)
64 return lhs.color.get_y()<rhs;
67 /* === P R O C E D U R E S ================================================= */
69 /* === M E T H O D S ======================================================= */
76 Palette::Palette(const String& name_):
82 PaletteItem::add(const Color& x,int xweight)
84 color=(color*weight+x*xweight)/(weight+xweight);
88 Palette::Palette(const Surface& surface, int max_colors):
89 name_(_("Surface Palette"))
92 for(int i=0;(signed)size()<(max_colors-1) && i<max_colors*16;++i) {
93 int x=rand()%surface.get_w();
94 int y=rand()%surface.get_h();
97 Color color(surface[y][x]);
107 if(front().color.get_a()!=0)
108 insert(begin(),Color(1,0,1,0));
113 iterator iter(find_closest(color,&dist));
120 /*if(size()>=max_colors)
122 iterator iterlight(find_light());
123 PaletteItem light(*iterlight);
125 find_closest(light.color)->add(light.color,light.weight);
136 for(int y=0;y<surface.get_h();y++)
137 for(int x=0;x<surface.get_w();x++)
140 Color color(surface[y][x]);
150 if(front().color.get_a()!=0)
151 insert(begin(),Color(1,0,1,0));
156 iterator iter(find_closest(color,&dist));
167 sort(rbegin(),rend());
171 iterator best_match(begin());
172 while((signed)size()>max_colors)
174 PaletteItem item(back());
176 find_closest(item.color)->add(item.color,item.weight);
179 push_back(Color::black());
180 push_back(Color::white());
182 // sort(begin(),end(),&luma_less_than);
185 Palette::const_iterator
186 Palette::find_closest(const Color& color, float* dist)const
188 // For the sake of avoiding cut-and-paste
189 // bugs, we'll just use the non-const
190 // find_closest()... It doesn't change anything
192 return const_cast<Palette*>(this)->find_closest(color,dist);
196 Palette::find_closest(const Color& color, float* dist)
200 iterator best_match(begin());
201 float best_dist(1000000);
203 const float prep_y(powf(color.get_y(),2.2f)*color.get_a());
204 const float prep_u(color.get_u());
205 const float prep_v(color.get_v());
207 for(iter=begin();iter!=end();++iter)
209 const float diff_y(prep_y-powf(iter->color.get_y(),2.2f)*iter->color.get_a());
210 const float diff_u(prep_u-iter->color.get_u());
211 const float diff_v(prep_v-iter->color.get_v());
212 const float diff_a(color.get_a()-iter->color.get_a());
224 prep_u*iter->color.get_u()-
225 prep_v*iter->color.get_v()
242 Palette::find_heavy()
246 iterator best_match(begin());
248 for(iter=begin();iter!=end();++iter)
250 if(iter->weight>best_match->weight)
258 Palette::find_light()
262 iterator best_match(begin());
264 for(iter=begin();iter!=end();++iter)
266 if(iter->weight<best_match->weight)
274 Palette::grayscale(int steps)
277 for(int i=0;i<steps;i++)
279 float amount(i/(steps-1));
280 float y(powf(amount,2.2f));
284 strprintf(_("%0.2f%% Gray"),amount)
292 Palette::save_to_file(const synfig::String& filename)const
296 std::ofstream file(filename.c_str());
299 throw strprintf(_("Unable to open %s for write"),filename.c_str());
301 file<<PALETTE_FILE_COOKIE<<endl;
303 for(iter=begin();iter!=end();++iter)
305 file<<iter->name<<endl;
307 <<iter->color.get_r()<<endl
308 <<iter->color.get_g()<<endl
309 <<iter->color.get_b()<<endl
310 <<iter->color.get_a()<<endl;
316 Palette::load_from_file(const synfig::String& filename)
318 std::ifstream file(filename.c_str());
321 throw strprintf(_("Unable to open %s for read"),filename.c_str());
328 if(line!=PALETTE_FILE_COOKIE)
329 throw strprintf(_("%s does not appear to be a palette file"),filename.c_str());
331 getline(file,ret.name_);
336 getline(file,item.name);
337 if(!file.eof())break;
340 if(!file.eof())break;
341 item.color.set_r(atof(line.c_str()));
344 if(!file.eof())break;
345 item.color.set_g(atof(line.c_str()));
348 if(!file.eof())break;
349 item.color.set_b(atof(line.c_str()));
352 if(!file.eof())break;
353 item.color.set_a(atof(line.c_str()));