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

color_hold.cc

// timfx 
// Copyright 2002, Timothy M. Shead
//
// Contact: tshead@k-3d.com
//
// 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 "color_hold.h"
#include "kino_plugin_types.h"

#include <kino/image_filters.h>

#include <gtkmm/adjustment.h>
#include <gtkmm/box.h>
#include <gtkmm/checkbutton.h>
#include <gtkmm/colorselection.h>
#include <gtkmm/label.h>
#include <gtkmm/spinbutton.h>
#include <gtkmm/main.h>
#include <gtkmm/window.h>

#include <algorithm>
#include <functional>
#include <iostream>
#include <set>
#include <string>
#include <vector>

namespace
{

class color_hold :
      public GDKImageFilter
{
public:
      color_hold() :
            m_color(0, 1, 1),
            m_tolerance(0.1),
            m_softness(0.1)
      {
            Gtk::Main main(0, 0);

            // Setup our user interface ...
            m_color_selection.set_has_opacity_control(false);

            Gtk::HBox* const color_group = new Gtk::HBox(false, 0);
            color_group->pack_start(m_color_selection, false, true);
            
            m_tolerance_spin_button.set_adjustment(*manage(new Gtk::Adjustment(m_softness, 0.0, 1.0, 0.01, 0.1)));
            m_tolerance_spin_button.set_numeric(true);
            m_tolerance_spin_button.set_digits(2);
            m_tolerance_spin_button.set_wrap(false);
            m_tolerance_spin_button.set_snap_to_ticks(true);

            m_softness_spin_button.set_adjustment(*manage(new Gtk::Adjustment(m_softness, 0.0, 1.0, 0.01, 0.1)));
            m_softness_spin_button.set_numeric(true);
            m_softness_spin_button.set_digits(2);
            m_softness_spin_button.set_wrap(false);
            m_softness_spin_button.set_snap_to_ticks(true);

            Gtk::HBox* const options_group = new Gtk::HBox(false, 0);
            options_group->pack_start(*manage(new Gtk::Label("Tolerance:")), false, true);
            options_group->pack_start(m_tolerance_spin_button, true, true);
            Gtk::HBox* const options_group2 = new Gtk::HBox(false, 0);
            options_group2->pack_start(*manage(new Gtk::Label("Softness:")), false, true);
            options_group2->pack_start(m_softness_spin_button, true, true);

            Gtk::VBox* const vbox = new Gtk::VBox(false, 0);
            vbox->pack_start(*manage(color_group), false, true);
            vbox->pack_start(*manage(options_group), false, true);
            vbox->pack_start(*manage(options_group2), false, true);
            vbox->show_all();

            m_window.add(*manage(vbox));
      }

      char *GetDescription( ) const
      {
            return "Color Hold"; 
      }

      void FilterFrame(uint8_t* pixels, int width, int height, double position, double frame_delta)
      {
            // For each pixel in the source data ...
            const kino::basic_rgb<uint8_t>* const end = reinterpret_cast<kino::basic_rgb<uint8_t>*>(pixels) + width * height;
            for(kino::basic_rgb<uint8_t>* pixel = reinterpret_cast<kino::basic_rgb<uint8_t>*>(pixels); pixel != end; ++pixel)
                  {
                        const uint8_t weighted_luma = kino::color_traits<uint8_t>::convert(0.299 * kino::color_traits<double>::convert(pixel->red) + 0.587 * kino::color_traits<double>::convert(pixel->green) + 0.114 * kino::color_traits<double>::convert(pixel->blue));
                  
                        kino::basic_hsv hsv_pixel(*pixel);

                        double d = m_color.hue - hsv_pixel.hue;
                        while(d < -180)
                              d += 360;
                        while(d > 180)
                              d -= 360;
                                          
                        d /= 180;
                        
                        d = fabs(d);
                        
                        d = kino::linearstep(m_tolerance, m_tolerance + m_softness, d);
                        
                        pixel->red = kino::lerp(pixel->red, weighted_luma, d);
                        pixel->green = kino::lerp(pixel->green, weighted_luma, d);
                        pixel->blue = kino::lerp(pixel->blue, weighted_luma, d);
                  }
      }

      void AttachWidgets(GtkBin* bin)
      {
            gtk_widget_reparent( ( GTK_BIN( m_window.gobj() ) )->child, GTK_WIDGET( bin ) );
      }

      void DetachWidgets(GtkBin* bin)
      {
            gtk_widget_reparent( ( GTK_BIN( bin ) )->child, GTK_WIDGET( m_window.gobj() ) );
      }

      void InterpretWidgets( GtkBin *bin )
      {
            Gdk::Color color;
            color = m_color_selection.get_current_color();
            m_color = kino::basic_rgb<double>(color.get_red(), color.get_green(), color.get_blue());
      
            m_tolerance = m_tolerance_spin_button.get_value();
            m_softness = m_softness_spin_button.get_value();
      }

private:
      Gtk::ColorSelection m_color_selection;
      Gtk::SpinButton m_tolerance_spin_button;
      Gtk::SpinButton m_softness_spin_button;
      
      kino::basic_hsv m_color;
      double m_tolerance;
      double m_softness;

      Gtk::Window m_window;
};

} // namespace

GDKImageFilter* color_hold_factory()
{
      return new color_hold();
}

Generated by  Doxygen 1.6.0   Back to index