/* === S Y N F I G ========================================================= */ /*! \file palette.cpp ** \brief Template File ** ** $Id$ ** ** \legal ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley ** Copyright (c) 2010 Nikita Kitaev ** Copyright (c) 2010 Carlos López ** ** This package is free software; you can redistribute it and/or ** modify it under the terms of the GNU General Public License as ** published by the Free Software Foundation; either version 2 of ** the License, or (at your option) any later version. ** ** This package is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ** General Public License for more details. ** \endlegal */ /* ========================================================================= */ /* === H E A D E R S ======================================================= */ #ifdef USING_PCH # include "pch.h" #else #ifdef HAVE_CONFIG_H # include #endif #include "palette.h" #include "surface.h" #include "general.h" #include #include #endif /* === U S I N G =========================================================== */ using namespace std; using namespace etl; using namespace synfig; /* === M A C R O S ========================================================= */ #define PALETTE_SYNFIG_FILE_COOKIE "SYNFIGPAL1.0" #define PALETTE_SYNFIG_EXT "spal" #define PALETTE_GIMP_FILE_COOKIE "GIMP Palette" #define PALETTE_GIMP_EXT "gpl" /* === G L O B A L S ======================================================= */ bool weight_less_than(const PaletteItem& lhs,const PaletteItem& rhs) { return lhs.weightadd(color); continue; } /*if(size()>=max_colors) { iterator iterlight(find_light()); PaletteItem light(*iterlight); erase(iterlight); find_closest(light.color)->add(light.color,light.weight); } */ push_back(color); continue; } /* max_colors-=2; for(int y=0;yadd(color); continue; } push_back(color); continue; } sort(rbegin(),rend()); iterator iter; iterator best_match(begin()); while((signed)size()>max_colors) { PaletteItem item(back()); pop_back(); find_closest(item.color)->add(item.color,item.weight); } */ push_back(Color::black()); push_back(Color::white()); // sort(begin(),end(),&luma_less_than); } Palette::const_iterator Palette::find_closest(const Color& color, float* dist)const { // For the sake of avoiding cut-and-paste // bugs, we'll just use the non-const // find_closest()... It doesn't change anything // anyway. return const_cast(this)->find_closest(color,dist); } Palette::iterator Palette::find_closest(const Color& color, float* dist) { iterator iter; iterator best_match(begin()); float best_dist(1000000); const float prep_y(powf(color.get_y(),2.2f)*color.get_a()); const float prep_u(color.get_u()); const float prep_v(color.get_v()); for(iter=begin();iter!=end();++iter) { const float diff_y(prep_y-powf(iter->color.get_y(),2.2f)*iter->color.get_a()); const float diff_u(prep_u-iter->color.get_u()); const float diff_v(prep_v-iter->color.get_v()); const float diff_a(color.get_a()-iter->color.get_a()); const float dist( diff_y*diff_y*1.5f+ diff_a*diff_a+ diff_u*diff_u+ diff_v*diff_v // cross product /*abs( prep_u*iter->color.get_u()- prep_v*iter->color.get_v() )*/ ); if(distweight>best_match->weight) best_match=iter; } return best_match; } Palette::iterator Palette::find_light() { iterator iter; iterator best_match(begin()); for(iter=begin();iter!=end();++iter) { if(iter->weightweight) best_match=iter; } return best_match; } Palette Palette::grayscale(int steps) { Palette ret; for(int i=0;iname<color.get_r()<color.get_g()<color.get_b()<color.get_a()<>r>>g>>b>>a; item.color.set_r(r); item.color.set_g(g); item.color.set_b(b); item.color.set_a(a); if(file.eof()) break; ret.push_back(item); } } else if (ext==PALETTE_GIMP_EXT) { /* file format: GPL (GIMP Palette) file should have the following layout: GIMP Palette Name: ... # ... ... */ while(line=="" && !file.eof()) //drops empty first header lines in malformed files getline(file,line); if(line!=PALETTE_GIMP_FILE_COOKIE) throw strprintf(_("%s does not appear to be a valid %s palette file"),filename.c_str(),"GIMP"); getline(file,line); ret.name_=String(line.substr(6)); //drops 6 first chars from line (ie 'Name: ') while(line!="#" && !file.eof()) //drops remaining header lines getline(file,line); while(!file.eof()) { PaletteItem item; getline(file,line); //todo how to efficiently split stream line between spaces+ in C++? Perlregexp would be smthg like (\d{1-3})\s+(\d{1-3})\s+(\d{1-3})\s+(.*) float r(line.substr(0,3)), g(line.substr(4,3)), b(line.substr(8,3)); //todo does multiple declaration+init work; does float(String) trim the spaces? item.name=String(line.substr(12)); Color c(r/255,g/255,b/255); //alpha is 1 by default item.color=c; if(file.eof()) break; ret.push_back(item); } } else throw strprintf(_("%s does not appear to be a supported palette file"),filename.c_str()); return ret; }