Logo Search packages:      
Sourcecode: agave version File versions  Download package

gcs-color.cc

/*******************************************************************************
 *  PROJECT: GNOME Colorscheme
 *
 *  AUTHOR: Jonathon Jongsma
 *
 *  Copyright (c) 2005 Jonathon Jongsma
 *
 *  License:
 *    This program 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 program 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.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the 
 *    Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
 *    Boston, MA  02111-1307  USA
 *
 *******************************************************************************/

#include "gcs-color.h"
#include <sstream>              // for ostringstream, istringstream
#include <iomanip>              // for hex, setw, setfill
#include <algorithm>            // for transform
#include <stdexcept>            // for invalid_argument exception
#include "compat-round.h"    // for round, floor
#include "core/log-stream.h"

namespace gcs
{

    const double Color::m_redLuminance = 0.2126;
    const double Color::m_greenLuminance = 0.7152;
    const double Color::m_blueLuminance = 0.0722;

    ColorPtr Color::create(void)
    {
        ColorPtr clr(new Color());
        return clr;
    }


    ColorPtr Color::create(tHexString str)
    {
        ColorPtr clr(new Color(str));
        return clr;
    }


    ColorPtr Color::create(const gint r, const gint g, const gint b, const Glib::ustring name)
    {
        ColorPtr clr(new Color(r, g, b, name));
        return clr;
    }

    ColorPtr Color::create(const Gdk::Color& c)
    {
        ColorPtr clr(new Color(c));
        return clr;
    }

    ColorPtr Color::create(const Color& c)
    {
        ColorPtr clr(new Color(c));
        return clr;
    }


    Color::Color(void)
        : pColor(new Gdk::Color("#000000"))
    {
        //LOG("Created Color: " << get_hexstring());
    }


00081     Color::Color(tHexString hex)
        : pColor(new Gdk::Color())
    {
        set(hex);
        //LOG("Created Color: " << get_hexstring());
    }


00089     Color::Color(const gint r, const gint g, const gint b, const Glib::ustring name)
        : pColor(new Gdk::Color), m_name(name)
    {
        pColor->set_rgb_p(rgb_as_p(r), rgb_as_p(g), rgb_as_p(b));
        //LOG("Created Color: " << get_hexstring());
    }


00097     Color::Color(const Gdk::Color& c)
        : pColor(new Gdk::Color(c))
    {
        //LOG("Copied GDK Color: " << get_hexstring());
    }


00104     Color::Color(const Color& c)
    {
        pColor = std::auto_ptr<Gdk::Color>(new Gdk::Color(c.gdk()));
        m_name = c.m_name;
        //LOG("Copied Color: " << get_hexstring());
    }


00112     Color::~Color(void)
    {
        //LOG("Destroyed Color: " << get_hexstring());
    }


    Gdk::Color& Color::gdk(void) const
    {
        return *pColor;
    }

00123     void Color::set(const gint r, const gint g, const gint b, Glib::ustring name)
    {
        pColor->set_rgb_p(rgb_as_p(r), rgb_as_p(g), rgb_as_p(b));
        set_name(name);
    }

00129     bool Color::set(tHexString hex)
    {
        bool success = pColor->set(hex);
        if (!success)
        {
            success = pColor->set(normalize_hex(hex));
        }
        return success;
    }

00139     tColorRgb Color::get_rgb(void) const
    {
        tColorRgb rgb;
        rgb.red = get_red();
        rgb.green = get_green();
        rgb.blue = get_blue();
        return rgb;
    }

00148     tColorHsv Color::get_hsv(void) const
    {
        return rgb_to_hsv(get_rgb());
    }

00153     gint Color::get_hue(void) const
    {
        return rgb_to_hsv(get_rgb()).hue;
    }

00158     gint Color::get_saturation(void) const
    {
        return rgb_to_hsv(get_rgb()).saturation;
    }

00163     gint Color::get_value(void) const
    {
        return rgb_to_hsv(get_rgb()).value;
    }

00168     gint Color::get_red(void) const
    {
        return static_cast<gint>(compat_round(pColor->get_red_p() *
                    static_cast<gdouble>(maxRgbValue)));
    }


00175     void Color::set_red(gint r)
    {
        pColor->set_red(maxGdkColorValue * r / maxRgbValue);
    }


00181     gint Color::get_green(void) const
    {
        return static_cast<gint>(compat_round(pColor->get_green_p() *
                static_cast<gdouble>(maxRgbValue)));
    }


00188     void Color::set_green(gint g)
    {
        pColor->set_green(maxGdkColorValue * g / maxRgbValue);
    }


00194     gint Color::get_blue(void) const
    {
        return static_cast<gint>(compat_round(pColor->get_blue_p() *
                static_cast<gdouble>(maxRgbValue)));
    }


00201     void Color::set_blue(gint b)
    {
        pColor->set_blue(maxGdkColorValue * b / maxRgbValue);
    }


00207     void Color::set_hue(gint h)
    {
        tColorHsv hsv = get_hsv();
        hsv.hue = h;
        set_hsv(hsv);
    }


00215     void Color::set_saturation(gint s)
    {
        tColorHsv hsv = get_hsv();
        hsv.saturation = s;
        set_hsv(hsv);
    }


00223     void Color::set_value(gint v)
    {
        tColorHsv hsv = get_hsv();
        hsv.value = v;
        set_hsv(hsv);
    }

    void Color::set_hsv(tColorHsv hsv)
    {
        // Gdk::Color::set_hsv expects hue [0,360] and s and v [0,1]
        pColor->set_hsv(hsv.hue, 
                static_cast<gdouble>(hsv.saturation) / static_cast<gdouble>(maxSvValue),
                    static_cast<gdouble>(hsv.value) / static_cast<gdouble>(maxSvValue));
    }

00238     tHexString Color::get_hexstring(void) const
    {
        return rgb_to_hex(get_rgb());
    }


00244     void Color::set_name(Glib::ustring name)
    {
        m_name = name;
    }


00250     Glib::ustring Color::get_name(void) const
    {
        if (m_name.size())
            return m_name;
        else
            return get_hexstring();
    }


    gint Color::get_luminance(void) const
    {
        return static_cast<gint>(static_cast<double>(get_red()) * m_redLuminance
                + static_cast<double>(get_green()) * m_greenLuminance
                + static_cast<double>(get_blue()) * m_blueLuminance);
    }


00267     bool Color::operator==(const Color& c)
    {
        bool status = false;
        // first check if we're comparing it to itself, then check all of the
        // attributes to see if their values are the same
        if ((this == &c) || (*pColor == *c.pColor))
        {
            status = true;
        }
        else
        {
            if (get_hexstring() == c.get_hexstring())
            {
                status = true;
            }
        }
        return status;
    }


    bool Color::operator!=(const Color& c)
    {
        return !(*this == c);
    }


    bool Color::operator<(const Color& c)
    {
        return this->get_luminance() < c.get_luminance();
    }


    Color& Color::operator=(const Color& c)
    {
        // First check if we're trying to assign it to itself
        if (this != &c)
        {
            pColor = std::auto_ptr<Gdk::Color>(new Gdk::Color(*c.pColor));
        }
        return *this;
    }


    // r,g,b values are from 0 to 1 
    // h = [0,360], s = [0,1], v = [0,1]
    // if s == 0, then h = -1 (undefined)
00313     tColorHsv Color::rgb_to_hsv(const tColorRgb rgb)
    {
        gint min, max, delta;
        tColorHsv out;
        gdouble tempHue, tempSat, tempVal;

        min = MIN(MIN(rgb.red, rgb.green), rgb.blue);
        max = MAX(MAX(rgb.red, rgb.green), rgb.blue);
        tempVal = static_cast<gdouble>(maxSvValue) *
            (static_cast<gdouble>(max) / static_cast<gdouble>(maxRgbValue));

        delta = max - min;

        if(max != 0)
        {
            tempSat = static_cast<gdouble>(maxSvValue) *
                (static_cast<gdouble>(delta) / static_cast<gdouble>(max));
        }
        else
        {
            // red = green = blue = 0           // s = 0, v is undefined
            out.saturation = 0;
            out.hue = 0;
            out.value = static_cast<gint>(tempVal);
            return out;
        }

        // needs to be shifted to 0-255
        if(rgb.red == max)
        {
            if (delta != 0)
            {
                tempHue = static_cast<gdouble>(rgb.green - rgb.blue) /
                    static_cast<gdouble>(delta);            // between yellow & magenta
            }
            else
            {
                tempHue = 0;
            }
        }
        else if(rgb.green == max)
        {
            tempHue = 2.0 + static_cast<gdouble>(rgb.blue - rgb.red) /
                static_cast<gdouble>(delta);    // between cyan & yellow
        }
        else
        {
            tempHue = 4.0 + static_cast<gdouble>(rgb.red - rgb.green) /
                static_cast<gdouble>(delta);    // between magenta & cyan
        }

        tempHue *= static_cast<gdouble>(maxHueValue) / static_cast<gdouble>(6);                       // degrees
        tempHue = compat_round(tempHue);
        out.saturation = static_cast<gint>(compat_round(tempSat));
        out.value = static_cast<gint>(compat_round(tempVal));
        if(tempHue < 0)
        {
            tempHue += maxHueValue;
        }
        out.hue = static_cast<gint>(tempHue);

        return out;
    }


00378     tHexString Color::rgb_to_hex(const tColorRgb color)
    {
        std::ostringstream hString;

        hString << std::hex << std::setfill('0') << "#"
            << std::setw(2) << (gint) color.red
            << std::setw(2) << (gint) color.green
            << std::setw(2) << (gint) color.blue;

        return static_cast<tHexString>(hString.str());
    }


    gdouble Color::rgb_as_p(gint rgbVal)
    {
        return static_cast<gdouble>(static_cast<gdouble>(rgbVal) / 
                static_cast<gdouble>(maxRgbValue));
    }


    tHexString Color::normalize_hex(tHexString hex)
    {
        // FIXME: this is kinda hack-y but it works for limited situations --
        // it needs more intelligence
        Glib::ustring valid_chars = "#0123456789abcdefABCDEF";
        if (hex.find_first_not_of(valid_chars) == Glib::ustring::npos)
        {
            switch (hex.size())
            {
                case 3:
                    // make "abc" into "#aabbcc"
                    hex.insert(2, 1, hex[2]);
                    hex.insert(1, 1, hex[1]);
                    hex.insert(0, 1, hex[0]);
                    hex.insert(0, 1, '#');
                    break;
                case 6:
                    // make "aabbcc" into "#aabbcc"
                    hex.insert(0, 1, '#');
                    break;
                default:
                    ;   // do nothing
            }
        }
        return hex.lowercase();
    }


00426     std::ostream& operator<<(std::ostream& out, const Color c)
    {
        return out << std::setw(3) << c.get_red() << " "
            << std::setw(3) << c.get_green() << " "
            << std::setw(3) << c.get_blue() << " "
            << c.get_name();
    }


    std::ostream& operator<<(std::ostream& out, const ColorPtr c)
    {
        return out << *c;
    }

} // namespace gcs

Generated by  Doxygen 1.6.0   Back to index