1 /* === S Y N F I G ========================================================= */
3 ** \brief Template File
8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 ** Copyright (c) 2010 Nikita Kitaev
10 ** Copyright (c) 2010 Carlos López
12 ** This package is free software; you can redistribute it and/or
13 ** modify it under the terms of the GNU General Public License as
14 ** published by the Free Software Foundation; either version 2 of
15 ** the License, or (at your option) any later version.
17 ** This package is distributed in the hope that it will be useful,
18 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 ** General Public License for more details.
23 /* ========================================================================= */
25 /* === H E A D E R S ======================================================= */
42 /* === U S I N G =========================================================== */
46 using namespace synfig;
48 /* === M A C R O S ========================================================= */
50 #define PALETTE_FILE_COOKIE "SYNFIGPAL1.0"
52 /* === G L O B A L S ======================================================= */
54 bool weight_less_than(const PaletteItem& lhs,const PaletteItem& rhs)
56 return lhs.weight<rhs.weight;
59 bool luma_less_than(const PaletteItem& lhs,const PaletteItem& rhs)
61 return lhs.color.get_y()<rhs.color.get_y();
64 bool luma_less_than(const PaletteItem& lhs,const float& rhs)
66 return lhs.color.get_y()<rhs;
69 /* === P R O C E D U R E S ================================================= */
71 /* === M E T H O D S ======================================================= */
78 Palette::Palette(const String& name_):
84 PaletteItem::add(const Color& x,int xweight)
86 color=(color*weight+x*xweight)/(weight+xweight);
90 Palette::Palette(const Surface& surface, int max_colors):
91 name_(_("Surface Palette"))
94 for(int i=0;(signed)size()<(max_colors-1) && i<max_colors*16;++i) {
95 int x=rand()%surface.get_w();
96 int y=rand()%surface.get_h();
99 Color color(surface[y][x]);
109 if(front().color.get_a()!=0)
110 insert(begin(),Color(1,0,1,0));
115 iterator iter(find_closest(color,&dist));
122 /*if(size()>=max_colors)
124 iterator iterlight(find_light());
125 PaletteItem light(*iterlight);
127 find_closest(light.color)->add(light.color,light.weight);
138 for(int y=0;y<surface.get_h();y++)
139 for(int x=0;x<surface.get_w();x++)
142 Color color(surface[y][x]);
152 if(front().color.get_a()!=0)
153 insert(begin(),Color(1,0,1,0));
158 iterator iter(find_closest(color,&dist));
169 sort(rbegin(),rend());
173 iterator best_match(begin());
174 while((signed)size()>max_colors)
176 PaletteItem item(back());
178 find_closest(item.color)->add(item.color,item.weight);
181 push_back(Color::black());
182 push_back(Color::white());
184 // sort(begin(),end(),&luma_less_than);
187 Palette::const_iterator
188 Palette::find_closest(const Color& color, float* dist)const
190 // For the sake of avoiding cut-and-paste
191 // bugs, we'll just use the non-const
192 // find_closest()... It doesn't change anything
194 return const_cast<Palette*>(this)->find_closest(color,dist);
198 Palette::find_closest(const Color& color, float* dist)
202 iterator best_match(begin());
203 float best_dist(1000000);
205 const float prep_y(powf(color.get_y(),2.2f)*color.get_a());
206 const float prep_u(color.get_u());
207 const float prep_v(color.get_v());
209 for(iter=begin();iter!=end();++iter)
211 const float diff_y(prep_y-powf(iter->color.get_y(),2.2f)*iter->color.get_a());
212 const float diff_u(prep_u-iter->color.get_u());
213 const float diff_v(prep_v-iter->color.get_v());
214 const float diff_a(color.get_a()-iter->color.get_a());
226 prep_u*iter->color.get_u()-
227 prep_v*iter->color.get_v()
244 Palette::find_heavy()
248 iterator best_match(begin());
250 for(iter=begin();iter!=end();++iter)
252 if(iter->weight>best_match->weight)
260 Palette::find_light()
264 iterator best_match(begin());
266 for(iter=begin();iter!=end();++iter)
268 if(iter->weight<best_match->weight)
276 Palette::grayscale(int steps)
279 for(int i=0;i<steps;i++)
281 float amount(i/(steps-1));
282 float y(powf(amount,2.2f));
286 strprintf(_("%0.2f%% Gray"),amount)
294 Palette::save_to_file(const synfig::String& filename)const
298 std::ofstream file(filename.c_str());
301 throw strprintf(_("Unable to open %s for write"),filename.c_str());
303 file<<PALETTE_FILE_COOKIE<<endl;
305 for(iter=begin();iter!=end();++iter)
307 file<<iter->name<<endl;
309 <<iter->color.get_r()<<endl
310 <<iter->color.get_g()<<endl
311 <<iter->color.get_b()<<endl
312 <<iter->color.get_a()<<endl;
318 Palette::load_from_file(const synfig::String& filename)
320 std::ifstream file(filename.c_str());
323 throw strprintf(_("Unable to open %s for read"),filename.c_str());
330 if(line!=PALETTE_FILE_COOKIE)
331 throw strprintf(_("%s does not appear to be a palette file"),filename.c_str());
333 getline(file,ret.name_);
340 getline(file,item.name);
346 if(file.eof()) break;