/////////////////////////////////////////////////////////////////////////////// // Name: Palettes3D.h // Purpose: The class to create and store palette with 3 colours per entry // Author: Alex Thuering // Created: 05.11.2006 // RCS-ID: $Id: Palette3D.cpp,v 1.2 2006/12/06 14:53:37 ntalex Exp $ // Copyright: (c) Alex Thuering // Licence: GPL /////////////////////////////////////////////////////////////////////////////// #include "Palette3D.h" #include inline unsigned char getR(unsigned int c) { return (unsigned char) c; } inline unsigned char getG(unsigned int c) { return (unsigned char) (c >> 8); } inline unsigned char getB(unsigned int c) { return (unsigned char) (c >> 16); } inline int Colour2Int(const wxColour& colour) { return colour.Ok() ? (colour.Red()<<16) + (colour.Green()<<8) + colour.Blue() : -1; } inline wxColour Int2Colour(int colour) { return colour != -1 ? wxColour(getR(colour), getG(colour), getB(colour)) : wxColour(); } inline double getDinstance(int c1, int c2) { if (c1 == -1 && c2 == -1) return 0; else if (c1 == -1 || c2 == -1) return 768; return 0.299 * abs(getR(c1) - getR(c2)) + 0.587 * abs(getG(c1) - getG(c2)) + 0.114 * abs(getB(c1) - getB(c2)); } void Palette3D::Add(const wxColour& colour1, const wxColour& colour2, const wxColour& colour3) { int c1 = Colour2Int(colour1); int c2 = Colour2Int(colour2); int c3 = Colour2Int(colour3); for (int i = 0; i<(int)m_colours1.GetCount(); i++) { if (m_colours1[i] == c1 && m_colours2[i] == c2 && m_colours3[i] == c3) return; // duplicated entry } m_colours1.Add(c1); m_colours2.Add(c2); m_colours3.Add(c3); } bool Palette3D::Apply(wxColour& colour1, wxColour& colour2, wxColour& colour3) { if (m_colours1.GetCount() == 0) return false; int c1 = Colour2Int(colour1); int c2 = Colour2Int(colour2); int c3 = Colour2Int(colour3); int closest = 0; double d, dinstance = 3000; // max 3*768 for (int i = 0; i<(int)m_colours1.GetCount(); i++) { d = getDinstance(c1, m_colours1[i]) + getDinstance(c2, m_colours2[i]) + getDinstance(c3, m_colours3[i]); if (d < dinstance) { dinstance = d; closest = i; } } if (c1 != m_colours1[closest] || c2 != m_colours2[closest] || c3 != m_colours3[closest]) { colour1 = Int2Colour(m_colours1[closest]); colour2 = Int2Colour(m_colours2[closest]); colour3 = Int2Colour(m_colours3[closest]); return true; } return false; } void Palette3D::ReduceColours(int maxColours) { while ((int)m_colours1.GetCount() > maxColours) { int closest = 0; double d, dinstance = 3000; // max 3*768 for (int i = 0; i<(int)m_colours1.GetCount(); i++) for (int j = 0; j<(int)m_colours1.GetCount(); j++) if (i != j) { d = getDinstance(m_colours1[i], m_colours1[j]) + getDinstance(m_colours2[i], m_colours2[j]) + getDinstance(m_colours3[i], m_colours3[j]); if (d < dinstance) { dinstance = d; closest = j; } } m_colours1.RemoveAt(closest); m_colours2.RemoveAt(closest); m_colours3.RemoveAt(closest); } }