From 57b624ac96ad10bf641eea4f6e275b73f9bdcb5a Mon Sep 17 00:00:00 2001 From: Santanu Sinha Date: Fri, 4 Sep 2009 12:39:57 +0530 Subject: [PATCH] Modifications in editing infrastructure This patch introduces solang to GEGL. That is the primal infrastrutural change. Others are just supportive changes. Some operations have been added as proof of concept. + Introduction of GEGL based editing engine + Introduction of editing toolbar + Introduction of histogram in properties and editing + Introduction of cursor changer + Added the following editing operation: Scaling (Pixbuf based) Brightness (Gegl based) Contrast (Gegl based) Saturation (Pixbuf based) --- configure.ac | 3 + data/edit-toolbar.ui | 47 +++++ data/solang-editor.ui | 21 ++- data/solang-thumbnail-popup.ui | 2 +- data/solang.ui | 5 + src/Makefile.am | 1 + src/application/Makefile.am | 8 +- src/application/application.cpp | 2 + src/application/main-window.cpp | 30 +++- src/application/main-window.h | 16 ++- src/application/main.cpp | 24 +++ src/attribute/property-manager.cpp | 6 + src/attribute/property-manager.h | 3 + src/common/Makefile.am | 8 + src/common/cursor-changer.h | 34 +++ src/common/histogram-viewer.cpp | 179 +++++++++++++++++ src/common/histogram-viewer.h | 84 ++++++++ src/common/histogram.cpp | 323 ++++++++++++++++++++++++++++++ src/common/histogram.h | 75 +++++++ src/common/progress-observer.cpp | 2 + src/common/types.h | 16 ++ src/edit-engine/Makefile.am | 45 ++++ src/edit-engine/brightness-operation.cpp | 62 ++++++ src/edit-engine/brightness-operation.h | 52 +++++ src/edit-engine/buffer.cpp | 210 +++++++++++++++++++ src/edit-engine/buffer.h | 100 +++++++++ src/edit-engine/contrast-operation.cpp | 63 ++++++ src/edit-engine/contrast-operation.h | 52 +++++ src/edit-engine/desaturate-operation.cpp | 64 ++++++ src/edit-engine/desaturate-operation.h | 52 +++++ src/edit-engine/edit-engine.cpp | 89 ++++++++ src/edit-engine/edit-engine.h | 77 +++++++ src/edit-engine/edit-types.h | 41 ++++ src/edit-engine/edit-utils.h | 45 ++++ src/edit-engine/filter.cpp | 76 +++++++ src/edit-engine/filter.h | 76 +++++++ src/edit-engine/flip-operation.cpp | 64 ++++++ src/edit-engine/flip-operation.h | 59 ++++++ src/edit-engine/load-file.cpp | 61 ++++++ src/edit-engine/load-file.h | 50 +++++ src/edit-engine/operation.cpp | 107 ++++++++++ src/edit-engine/operation.h | 53 +++++ src/edit-engine/scale-operation.cpp | 64 ++++++ src/edit-engine/scale-operation.h | 52 +++++ src/editor/Makefile.am | 30 +++- src/editor/brightness-widget.cpp | 62 ++++++ src/editor/brightness-widget.h | 33 +++ src/editor/contrast-widget.cpp | 63 ++++++ src/editor/contrast-widget.h | 33 +++ src/editor/desaturate-widget.cpp | 52 +++++ src/editor/desaturate-widget.h | 33 +++ src/editor/desaturate.cpp | 88 ++++++++ src/editor/desaturate.h | 48 +++++ src/editor/edit-action-widget.cpp | 36 ++++ src/editor/edit-action-widget.h | 39 ++++ src/editor/editable-photo.cpp | 62 ++++++- src/editor/editable-photo.h | 29 ++- src/editor/editor-toolbar.cpp | 52 +++++ src/editor/editor-toolbar.h | 58 ++++++ src/editor/editor.cpp | 96 ++++++++- src/editor/editor.h | 32 +++ src/editor/flip-widget.cpp | 63 ++++++ src/editor/flip-widget.h | 49 +++++ src/editor/gegl-operation.cpp | 94 +++++++++ src/editor/gegl-operation.h | 51 +++++ src/editor/rotate-widget.cpp | 63 ++++++ src/editor/rotate-widget.h | 49 +++++ src/editor/scale-widget.cpp | 52 +++++ src/editor/scale-widget.h | 33 +++ src/editor/scale.cpp | 70 +++++++ src/editor/scale.h | 48 +++++ src/editor/stock-button.cpp | 21 ++ src/editor/stock-button.h | 22 ++ src/renderer/Makefile.am | 3 + src/renderer/editor-renderer.cpp | 133 +++++++++++-- src/renderer/editor-renderer.h | 12 +- 76 files changed, 4064 insertions(+), 48 deletions(-) create mode 100644 data/edit-toolbar.ui create mode 100644 src/common/cursor-changer.h create mode 100644 src/common/histogram-viewer.cpp create mode 100644 src/common/histogram-viewer.h create mode 100644 src/common/histogram.cpp create mode 100644 src/common/histogram.h create mode 100644 src/edit-engine/Makefile.am create mode 100644 src/edit-engine/brightness-operation.cpp create mode 100644 src/edit-engine/brightness-operation.h create mode 100644 src/edit-engine/buffer.cpp create mode 100644 src/edit-engine/buffer.h create mode 100644 src/edit-engine/contrast-operation.cpp create mode 100644 src/edit-engine/contrast-operation.h create mode 100644 src/edit-engine/desaturate-operation.cpp create mode 100644 src/edit-engine/desaturate-operation.h create mode 100644 src/edit-engine/edit-engine.cpp create mode 100644 src/edit-engine/edit-engine.h create mode 100644 src/edit-engine/edit-types.h create mode 100644 src/edit-engine/edit-utils.h create mode 100644 src/edit-engine/filter.cpp create mode 100644 src/edit-engine/filter.h create mode 100644 src/edit-engine/flip-operation.cpp create mode 100644 src/edit-engine/flip-operation.h create mode 100644 src/edit-engine/load-file.cpp create mode 100644 src/edit-engine/load-file.h create mode 100644 src/edit-engine/operation.cpp create mode 100644 src/edit-engine/operation.h create mode 100644 src/edit-engine/scale-operation.cpp create mode 100644 src/edit-engine/scale-operation.h create mode 100644 src/editor/brightness-widget.cpp create mode 100644 src/editor/brightness-widget.h create mode 100644 src/editor/contrast-widget.cpp create mode 100644 src/editor/contrast-widget.h create mode 100644 src/editor/desaturate-widget.cpp create mode 100644 src/editor/desaturate-widget.h create mode 100644 src/editor/desaturate.cpp create mode 100644 src/editor/desaturate.h create mode 100644 src/editor/edit-action-widget.cpp create mode 100644 src/editor/edit-action-widget.h create mode 100644 src/editor/editor-toolbar.cpp create mode 100644 src/editor/editor-toolbar.h create mode 100644 src/editor/flip-widget.cpp create mode 100644 src/editor/flip-widget.h create mode 100644 src/editor/gegl-operation.cpp create mode 100644 src/editor/gegl-operation.h create mode 100644 src/editor/rotate-widget.cpp create mode 100644 src/editor/rotate-widget.h create mode 100644 src/editor/scale-widget.cpp create mode 100644 src/editor/scale-widget.h create mode 100644 src/editor/scale.cpp create mode 100644 src/editor/scale.h create mode 100644 src/editor/stock-button.cpp create mode 100644 src/editor/stock-button.h diff --git a/configure.ac b/configure.ac index b2a9aff..7a6edf6 100644 --- a/configure.ac +++ b/configure.ac @@ -36,6 +36,8 @@ PKG_CHECK_MODULES(GTKMM, [gtkmm-2.4 >= 2.8]) PKG_CHECK_MODULES(SIGC, [sigc++-2.0]) PKG_CHECK_MODULES(SOUP, [libsoup-2.4]) PKG_CHECK_MODULES(WEBKIT, [webkit-1.0]) +PKG_CHECK_MODULES(BABL, [babl]) +PKG_CHECK_MODULES(GEGL, [gegl]) AC_OUTPUT([ @@ -46,6 +48,7 @@ src/application/Makefile src/attribute/Makefile src/common/Makefile src/database/Makefile +src/edit-engine/Makefile src/editor/Makefile src/exporter/Makefile src/importer/Makefile diff --git a/data/edit-toolbar.ui b/data/edit-toolbar.ui new file mode 100644 index 0000000..d8abde1 --- /dev/null +++ b/data/edit-toolbar.ui @@ -0,0 +1,47 @@ + + + + + + True + icons + 1 + + + True + ActionEditUndo + Undo + True + gtk-undo + + + False + True + + + + + True + EditActionRedo + Redo + True + gtk-redo + + + False + True + + + + + True + + + False + True + + + + + + diff --git a/data/solang-editor.ui b/data/solang-editor.ui index dbc97c0..b61a171 100644 --- a/data/solang-editor.ui +++ b/data/solang-editor.ui @@ -11,12 +11,29 @@ - + - + + + + + + + + + + + + + + + + + + diff --git a/data/solang-thumbnail-popup.ui b/data/solang-thumbnail-popup.ui index df99480..55b68e3 100644 --- a/data/solang-thumbnail-popup.ui +++ b/data/solang-thumbnail-popup.ui @@ -5,7 +5,7 @@ - + diff --git a/data/solang.ui b/data/solang.ui index 224e100..c8d00c8 100644 --- a/data/solang.ui +++ b/data/solang.ui @@ -40,4 +40,9 @@ + + + + + diff --git a/src/Makefile.am b/src/Makefile.am index 23a9f08..e2e380b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,6 +2,7 @@ SUBDIRS = \ attribute \ common \ database \ + edit-engine \ editor \ exporter \ importer \ diff --git a/src/application/Makefile.am b/src/application/Makefile.am index 0c2577f..ddd844b 100644 --- a/src/application/Makefile.am +++ b/src/application/Makefile.am @@ -23,6 +23,7 @@ solang_LDADD = \ $(top_builddir)/src/database/libdatabase.la \ $(top_builddir)/src/common/libcommon.la \ $(top_builddir)/src/editor/libeditor.la \ + $(top_builddir)/src/edit-engine/libeditengine.la \ $(EXIV2_LIBS) \ $(FLICKCURL_LIBS) \ $(GPHOTO2_LIBS) \ @@ -35,7 +36,9 @@ solang_LDADD = \ $(GIOMM_LIBS) \ $(GLIBMM_LIBS) \ $(GDL_LIBS) \ - $(SIGC_LIBS) + $(SIGC_LIBS) \ + $(BABL_LIBS) \ + $(GEGL_LIBS) AM_CPPFLAGS = \ -DPACKAGE_LOCALE_DIR=\""${datadir}/locale"\" \ @@ -62,7 +65,8 @@ AM_CPPFLAGS = \ $(GIOMM_CFLAGS) \ $(GLIBMM_CFLAGS) \ $(GDL_CFLAGS) \ - $(SIGC_CFLAGS) + $(SIGC_CFLAGS) \ + $(GEGL_CFLAGS) AM_CXXFLAGS = \ -Wall diff --git a/src/application/application.cpp b/src/application/application.cpp index 3abfdf4..7a3b559 100644 --- a/src/application/application.cpp +++ b/src/application/application.cpp @@ -349,6 +349,8 @@ Application::init() throw() mainWindow_.init(); + mainWindow_.connect_progress( engine_.get_default_observer() ); + initEnd_.emit(*this); } diff --git a/src/application/main-window.cpp b/src/application/main-window.cpp index 1323465..be544c5 100644 --- a/src/application/main-window.cpp +++ b/src/application/main-window.cpp @@ -29,6 +29,7 @@ #include #include "main-window.h" +#include "progress-observer.h" namespace Solang { @@ -51,7 +52,7 @@ class Docker : const GdlDockPlacement placement) throw(); Docker(const Docker & source) throw(); - + ~Docker() throw(); Docker & @@ -191,6 +192,8 @@ MainWindow::MainWindow() throw() : spinnerToolItem_(), hBox_(false, 6), statusBar_(), + progress_(), + observer_(), dock_(gdl_dock_new()), dockBar_(gdl_dock_bar_new(GDL_DOCK(dock_))), layout_(gdl_dock_layout_new(GDL_DOCK(dock_))), @@ -272,6 +275,8 @@ MainWindow::MainWindow() throw() : if (NULL != tool_bar) { + tool_bar->set_toolbar_style( Gtk::TOOLBAR_ICONS ); + //We don't need no stinkin' text :-P gtk_separator_tool_item_set_draw(separatorToolItem_.gobj(), FALSE); separatorToolItem_.set_expand(true); @@ -289,6 +294,7 @@ MainWindow::MainWindow() throw() : statusBar_.set_has_resize_grip(true); vBox_.pack_start(statusBar_, Gtk::PACK_SHRINK, 0); + statusBar_.pack_start( progress_, Gtk::PACK_EXPAND_WIDGET, 0); show_all_children(); } @@ -654,7 +660,7 @@ MainWindow::on_delete_event(GdkEventAny * event) bool return_value = Gtk::Window::on_delete_event(event); hide(); - return return_value; + return return_value; } void @@ -679,4 +685,24 @@ MainWindow::set_busy(bool busy) throw() spinnerToolItem_.set_spinning(busy); } +void +MainWindow::connect_progress( const ProgressObserverPtr &observer ) throw() +{ + observer_ = observer; + progress_.set_fraction( 0.0L ); + observer_->progress().connect( sigc::mem_fun(*this, + &MainWindow::handle_progress_event) ); +} + +void +MainWindow::handle_progress_event() throw() +{ + double percentage = + static_cast( + observer_->get_current_events()) + / static_cast( + observer_->get_num_events()) ; + progress_.set_fraction( percentage ); +} + } // namespace Solang diff --git a/src/application/main-window.h b/src/application/main-window.h index e74a3f8..c562823 100644 --- a/src/application/main-window.h +++ b/src/application/main-window.h @@ -37,7 +37,7 @@ class MainWindow : { public: MainWindow() throw(); - + virtual ~MainWindow() throw(); @@ -68,6 +68,11 @@ class MainWindow : void set_busy(bool busy) throw(); + void + connect_progress( + const ProgressObserverPtr &observer ) throw(); + + protected: std::string get_user_layout_file() throw(); @@ -91,6 +96,9 @@ class MainWindow : virtual bool on_delete_event(GdkEventAny * event); + void + handle_progress_event() throw(); + ActionGroupPtr actionGroup_; UIManagerPtr uiManager_; @@ -107,8 +115,12 @@ class MainWindow : Gtk::Statusbar statusBar_; + Gtk::ProgressBar progress_; + + ProgressObserverPtr observer_; + GtkWidget * const dock_; - + GtkWidget * const dockBar_; GdlDockLayout * const layout_; diff --git a/src/application/main.cpp b/src/application/main.cpp index 8f21b90..d368d83 100644 --- a/src/application/main.cpp +++ b/src/application/main.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -46,6 +47,7 @@ main(int argc, char *argv[]) Glib::thread_init(); Gio::init(); Gnome::Gda::init(PACKAGE_NAME, PACKAGE_VERSION, argc, argv); + gegl_init( &argc, &argv ); if (0 != flickcurl_init()) { @@ -57,6 +59,28 @@ main(int argc, char *argv[]) Glib::set_application_name(_(PACKAGE_NAME)); Gtk::Main kit(argc, argv, true); + GeglConfig *pConfig = gegl_config(); + { + GValue cacheSize = {0}; + g_value_init( &cacheSize, G_TYPE_INT ); + g_value_set_int( &cacheSize, 102400 ); + g_object_set_property( (GObject *)pConfig, "cache-size", &cacheSize ); + g_value_unset( &cacheSize ); + } + { + GValue quality = {0}; + g_value_init( &quality, G_TYPE_DOUBLE ); + g_value_set_double( &quality, 0.1 ); + g_object_set_property( (GObject *)pConfig, "quality", &quality ); + g_value_unset( &quality ); + } + { + GValue swap = {0}; + g_value_init( &swap, G_TYPE_STRING ); + g_value_set_string( &swap, "/tmp" ); + g_object_set_property( (GObject *)pConfig, "swap", &swap ); + g_value_unset( &swap ); + } Solang::Application application(argc, argv); application.init(); diff --git a/src/attribute/property-manager.cpp b/src/attribute/property-manager.cpp index c9cc705..905fd53 100644 --- a/src/attribute/property-manager.cpp +++ b/src/attribute/property-manager.cpp @@ -51,6 +51,8 @@ PropertyManager::PropertyManager() throw() : vBox_(false, 6), basicInfo_(), basicExifView_(), + histBox_(), + histogram_(), signalRendererChanged_() { dockItem_ = gdl_dock_item_new_with_stock(dockItemName_.c_str(), @@ -64,7 +66,10 @@ PropertyManager::PropertyManager() throw() : Gtk::POLICY_AUTOMATIC); basicInfo_.add(basicExifView_); + histBox_.pack_start( histogram_, Gtk::PACK_SHRINK, 6 ); + noteBook_.append_page( vBox_, _("Basic") ); + noteBook_.append_page( histBox_, _("Histogram") ); vBox_.pack_start( basicInfo_, Gtk::PACK_EXPAND_WIDGET,0 ); } @@ -174,6 +179,7 @@ PropertyManager::on_selection_changed() throw() return; basicExifView_.populate( (*photos.begin())->get_exif_data() ); + histogram_.set((*photos.begin())->get_thumbnail_buffer()); return; } diff --git a/src/attribute/property-manager.h b/src/attribute/property-manager.h index ed25f61..f1d7230 100644 --- a/src/attribute/property-manager.h +++ b/src/attribute/property-manager.h @@ -27,6 +27,7 @@ #include "plugin.h" #include "basic-exif-view.h" +#include "histogram-viewer.h" namespace Solang { @@ -96,6 +97,8 @@ protected: Gtk::VBox vBox_; Gtk::ScrolledWindow basicInfo_; BasicExifView basicExifView_; + Gtk::VBox histBox_; + HistogramViewer histogram_; sigc::connection signalRendererChanged_; diff --git a/src/common/Makefile.am b/src/common/Makefile.am index a08ab86..d39ef74 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -3,10 +3,15 @@ noinst_LTLIBRARIES = libcommon.la libcommon_la_SOURCES = \ content-type-repo.cpp \ content-type-repo.h \ + cursor-changer.h \ error.cpp \ error.h \ flickr-context.cpp \ flickr-context.h \ + histogram-viewer.cpp \ + histogram-viewer.h \ + histogram.cpp \ + histogram.h \ id-base.h \ id-repo.cpp \ id-repo.h \ @@ -54,6 +59,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/attribute \ -I$(top_srcdir)/src/common \ -I$(top_srcdir)/src/database \ + -I$(top_srcdir)/src/edit-engine \ -I$(top_srcdir)/src/importer \ -I$(top_srcdir)/src/renderer \ -I$(top_srcdir)/src/storage \ @@ -65,6 +71,8 @@ AM_CPPFLAGS = \ $(GIOMM_CFLAGS) \ $(GLIBMM_CFLAGS) \ $(GDL_CFLAGS) \ + $(GEGL_CFLAGS) \ + $(BABL_CFLAGS) \ $(SIGC_CFLAGS) AM_CXXFLAGS = \ diff --git a/src/common/cursor-changer.h b/src/common/cursor-changer.h new file mode 100644 index 0000000..c48ba70 --- /dev/null +++ b/src/common/cursor-changer.h @@ -0,0 +1,34 @@ +#ifndef SOLANG_CURSOR_CHANGER_H +#define SOLANG_CURSOR_CHANGER_H + +namespace Solang +{ + +class CursorChanger +{ + public: + CursorChanger(Gtk::Widget &widget) + :widget_( widget ) + { + widget_.get_window()->set_cursor( + Gdk::Cursor( widget_.get_display(), + Gdk::WATCH ) ); + widget_.set_sensitive( false ); + } + + ~CursorChanger() + { + widget_.get_window()->set_cursor(); + widget_.set_sensitive( true ); + } + + + private: + Gtk::Widget &widget_; + +}; + +} + +#endif //SOLANG_CURSOR_CHANGER_H + diff --git a/src/common/histogram-viewer.cpp b/src/common/histogram-viewer.cpp new file mode 100644 index 0000000..6cec06e --- /dev/null +++ b/src/common/histogram-viewer.cpp @@ -0,0 +1,179 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif //HAVE_CONFIG_H + +#include + +#include "histogram-viewer.h" + +namespace Solang +{ + +HistogramViewer::HistogramViewer( bool autoupdate ) + :histogram_(), + width_( 192 ), + height_( 144 ), + image_(), + histogramView_(), + hbType_(), + lblType_( _("Type") ), + typeCols_(), + typeStore_( Gtk::ListStore::create( typeCols_ ) ), + cmbType_(), + hbChannels_(), + lblChannels_( _("Channels") ), + channelCols_(), + channelStore_( Gtk::ListStore::create( channelCols_ ) ), + cmbChannels_(), + autoupdate_( true ) +{ + hbType_.pack_start( lblType_, Gtk::PACK_SHRINK, 6 ); + hbType_.pack_start( cmbType_, Gtk::PACK_EXPAND_WIDGET, 6 ); + pack_start( hbType_, Gtk::PACK_EXPAND_WIDGET, 6); + + histogramView_.set_size_request( 192, 144 ); + pack_start(histogramView_, Gtk::PACK_EXPAND_WIDGET, 6); + + hbChannels_.pack_start( lblChannels_, Gtk::PACK_SHRINK, 6 ); + hbChannels_.pack_end( cmbChannels_, Gtk::PACK_EXPAND_WIDGET, 6 ); + pack_start( hbChannels_, Gtk::PACK_SHRINK, 6 ); + + cmbType_.set_model( typeStore_ ); + cmbType_.pack_start( typeCols_.name_ ); + cmbChannels_.set_model( channelStore_ ); + cmbChannels_.pack_start( channelCols_.name_ ); + //Types + { + Gtk::TreeModel::Row row = *(typeStore_->append()); + row[ typeCols_.type_ ] = Histogram::LINEAR; + row[ typeCols_.name_ ] = _("Linear") ; + } + { + Gtk::TreeModel::Row row = *(typeStore_->append()); + row[ typeCols_.type_ ] = Histogram::LOGARITHMIC; + row[ typeCols_.name_ ] = _("Logarithmic") ; + } + cmbType_.set_active( 0 ); + + //Channels + { + Gtk::TreeModel::Row row = *(channelStore_->append()); + row[ channelCols_.channel_ ] = Histogram::RGB; + row[ channelCols_.name_ ] = _("RGB") ; + } + { + Gtk::TreeModel::Row row = *(channelStore_->append()); + row[ channelCols_.channel_ ] = Histogram::RED; + row[ channelCols_.name_ ] = _("Red") ; + } + { + Gtk::TreeModel::Row row = *(channelStore_->append()); + row[ channelCols_.channel_ ] = Histogram::GREEN; + row[ channelCols_.name_ ] = _("Green") ; + } + { + Gtk::TreeModel::Row row = *(channelStore_->append()); + row[ channelCols_.channel_ ] = Histogram::BLUE; + row[ channelCols_.name_ ] = _("Blue") ; + } + cmbChannels_.set_active( 0 ); + + cmbType_.signal_changed().connect( + sigc::mem_fun( *this, &HistogramViewer::update ) ); + cmbChannels_.signal_changed().connect( + sigc::mem_fun( *this, &HistogramViewer::update ) ); + show_all_children(); + signal_size_request().connect( + sigc::mem_fun( *this, + &HistogramViewer::size_changed )); + update(); +} + +HistogramViewer::~HistogramViewer() +{ +} + +void +HistogramViewer::set( const Glib::RefPtr &image ) +{ + image_ = image; + if( image_ ) + { + Histogram::DataBuffer imageData; + imageData.data_ = image_->get_pixels(); + imageData.bitsPerChannel_ = image_->get_bits_per_sample(); + imageData.numChannels_ = image_->get_n_channels(); + imageData.width_ = image_->get_width(); + imageData.height_ = image_->get_height(); + imageData.rowstride_ = image_->get_rowstride(); + histogram_.createData( imageData ); + } + if( true == autoupdate_ ) + update(); +} + +void +HistogramViewer::set_auto_update( bool autoupdate ) +{ + autoupdate_ = autoupdate; +} + +void +HistogramViewer::update() +{ + Gtk::TreeModel::const_iterator typeI + = cmbType_.get_active(); + Gtk::TreeModel::Row typeR = (*typeI); + Histogram::Type type = typeR[ typeCols_.type_ ]; + Gtk::TreeModel::const_iterator channelI + = cmbChannels_.get_active(); + Gtk::TreeModel::Row channelR = (*channelI); + Histogram::Channel channel + = channelR[ channelCols_.channel_ ]; + Glib::RefPtr pixbuf + = histogram_.get_pixbuf( type, width_, height_, channel ); + histogramView_.set( pixbuf ); + return; +} +void +HistogramViewer::on_size_request( Gtk::Requisition *requisition ) +{ + gint64 oldWidth = get_width(); + gint64 oldHeight = get_height(); + Gtk::VBox::on_size_request( requisition ); +#if 0 + gint64 width = width_ + requisition->width - oldWidth; + gint64 height = height_ + requisition->height - oldHeight; + width_ = (width > 0 ) ? width : width_; + height_ = (height > 0 ) ? height : height_; +#endif + //if( width_ > 0 && height_ > 0 ) + // histogramView_.set_size_request( width_, height_ ); + width_ = requisition->width; +// height_ = requisition->height; +#if 0 + freeze_child_notify(); + Glib::RefPtr buffer + = histogramView_.get_pixbuf(); + if( !buffer ) + return; + histogramView_.set( buffer->scale_simple( width_, height_, + Gdk::INTERP_HYPER ) ); + thaw_child_notify(); +#endif + //update(); +} + +void +HistogramViewer::size_changed(Gtk::Requisition *req) +{ +#if 0 + int width = req->width; + int height = get_height(); + width_ = width; + //update(); +#endif + +} + +} //namespace Solang diff --git a/src/common/histogram-viewer.h b/src/common/histogram-viewer.h new file mode 100644 index 0000000..fd43751 --- /dev/null +++ b/src/common/histogram-viewer.h @@ -0,0 +1,84 @@ +#ifndef SOLANG_HISTOGRAM_VIEWER_H +#define SOLANG_HISTOGRAM_VIEWER_H + +#include +#include "histogram.h" + +namespace Solang +{ + +class HistogramViewer + : public Gtk::VBox +{ + private: + class TypeSelectColumns + : public Gtk::TreeModel::ColumnRecord + { + public: + + TypeSelectColumns() + { + add( type_ ); + add( name_ ); + } + + Gtk::TreeModelColumn type_; + Gtk::TreeModelColumn name_; + }; + class ChannelSelectColumns + : public Gtk::TreeModel::ColumnRecord + { + public: + + ChannelSelectColumns() + { + add( channel_ ); + add( name_ ); + } + + Gtk::TreeModelColumn channel_; + Gtk::TreeModelColumn name_; + }; + + + public: + HistogramViewer( bool autoupdate = false ); + ~HistogramViewer(); + + void + set( const Glib::RefPtr &image ); + + void + set_auto_update( bool autoupdate = true ); + + void + update(); //Not required if autoupdate is set + + private: + void + on_size_request(Gtk::Requisition *req); + void + size_changed(Gtk::Requisition *req); + + Histogram histogram_; + gsize width_; + gsize height_; + Glib::RefPtr image_; + Gtk::Image histogramView_; + Gtk::HBox hbType_; + Gtk::Label lblType_; + TypeSelectColumns typeCols_; + Glib::RefPtr typeStore_; + Gtk::ComboBox cmbType_; + Gtk::HBox hbChannels_; + Gtk::Label lblChannels_; + ChannelSelectColumns channelCols_; + Glib::RefPtr channelStore_; + Gtk::ComboBox cmbChannels_; + bool autoupdate_; + +}; + +} //namespace Solang + +#endif //SOLANG_HISTOGRAM_VIEWER_H diff --git a/src/common/histogram.cpp b/src/common/histogram.cpp new file mode 100644 index 0000000..caa1edb --- /dev/null +++ b/src/common/histogram.cpp @@ -0,0 +1,323 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include + +#include "histogram.h" + +namespace Solang +{ + +Histogram::Histogram() + :data_(NULL), + maxLevel_(0), + buffer_() +{ + max[0]=max[1]=max[2]=0; +} + +Histogram::~Histogram() +{ + cleanup(); +} + +void +Histogram::createData( const Histogram::DataBuffer &data ) +{ + if( NULL != data_ ) + cleanup(); + buffer_ = data; + //Buffer is a 2D data-buffer + //Rows = 2^bitsPerChannel (256 for 8bit) + //Columns = 5 (R,G,B,A,Value) + gsize levels = 1 << data.bitsPerChannel_; + gsize channels = data.numChannels_; + gsize rowStride = data.rowstride_; + data_ = g_new0( guint32 *, channels ); + for(guint channel = 0; channel < channels; channel++ ) + { + data_[ channel ] = g_new0( guint32, levels ); + ::bzero( data_[ channel ], levels * sizeof(guint32) ); + } + guint8 *pixelData = data.data_; + + //Buffer is created + guint8 *line = pixelData; + for( gsize i = 0; i < data.height_; i ++ ) + { + guint8 *pixel = line; + line += rowStride; + for( gsize j = 0; j < data.width_; j ++ ) + { + data_[ RED ][ pixel[ RED ] ]++; + data_[ GREEN ][ pixel[ GREEN ] ]++; + data_[ BLUE ][ pixel[ BLUE ] ]++; + pixel += data.numChannels_; + } + } + + max[RED]=max[GREEN]=max[BLUE]=0; + for( gsize i = 0; i < levels; i++ ) + { + guint32 r = data_[ RED ][ i ]; + guint32 g = data_[ GREEN ][ i ]; + guint32 b = data_[ BLUE ][ i ]; + max[RED] = ( max[RED] < r )?r:max[RED]; + max[GREEN] = ( max[GREEN] < g )?g:max[GREEN]; + max[BLUE] = ( max[BLUE]< b )?b:max[BLUE]; + } + guint64 total = 0L; + for( gsize i = 0; i < channels; i++ ) + { + for( gsize j = 0; j < levels; j++ ) + { + maxLevel_ = ( maxLevel_ < data_[ i ][ j ] ) + ? data_[ i ][ j ] : maxLevel_; + total += data_[ i ][ j ]; + } + } +} + +Glib::RefPtr +Histogram::get_pixbuf( Type type, gsize width, gsize height, + Channel channel ) throw() +{ + if( Histogram::LINEAR == type ) + { + return get_linear_histogram( width, height, channel ); + } + return get_logarithmic_histogram( + width, height, channel ); +} + +Glib::RefPtr +Histogram::get_logarithmic_histogram( + gsize resultWidth, gsize resultHeight, + Histogram::Channel resultChannel) throw() +{ + gsize maxLevel = 1 << buffer_.bitsPerChannel_; + gsize width = maxLevel; + gsize height = maxLevel; + guint8 *pixels = g_new0( guint8, width * height * 3); + memset( pixels, 0x28, 3 * width * height ); //dark grey + + //Grid lines + for( guint32 i = 0; i < width; i += 64 ) + { + for( guint32 j = 0; j < height; j+=4 ) + { + guint8 *fill = ( pixels + ( i + j * width ) * 3 ); + fill[ RED ] = fill[ GREEN ] = fill[ BLUE ] = 0x73; + } + } + for( guint32 i = 0; i < width; i +=4 ) + { + for( guint32 j = 0; j < height; j+=64 ) + { + guint8 *fill = ( pixels + ( i + j * width ) * 3 ); + fill[ RED ] = fill[ GREEN ] = fill[ BLUE ] = 0x73; + } + } + if( !data_ ) + { + Glib::RefPtr buf + = Gdk::Pixbuf::create_from_data( + (guint8 *)pixels, + Gdk::COLORSPACE_RGB, + false, + 8, + width, + height, + 3 * width )->flip( false )-> + add_alpha(false, 0, 0, 0)->scale_simple( + resultWidth, resultHeight, + Gdk::INTERP_HYPER); + if( pixels ) + g_free( pixels ); + + return buf; + } + + for( gsize i = 0; i < maxLevel; i++ ) + { + //we have to set rgb and A for each pixel + // and we are going L2R + + //Considering we use only RGB channels + guint8 channel = 0; + guint32 maxVal = 0; + for( ; channel < 3; channel++ ) + { + double level = (double)data_[ channel ][ i ]; + double logLvl = (level>0)?log(level):0.0; + double logMax = (max[channel]>0)?log((double)max[channel]):1.0; + guint32 normLvl = (guint32)((double)( logLvl/logMax) * (double)(height-1)); + maxVal = ( maxVal < normLvl ) ? normLvl : maxVal; + if( RGB == resultChannel + || channel == resultChannel ) + { + for( gsize j = 0; j <= normLvl; j++ ) + { + Pixel *fill = (Pixel *)( + pixels + (i + j * width)*3); + fill->channels_[ channel ] + |= (j + 2 > normLvl ) ? 0xFF : 0xAA; + } + } + } + + //Demarkate value channel + for(guint32 j = maxVal - ((maxVal > 0 )?1:0); + j <= maxVal; j++ ) + { + guint8 *fill = (pixels + (i + j * width)*3); + fill[ RED ] = fill[ GREEN ] = fill[ BLUE ] = 0xFF; + } + } + + Glib::RefPtr buf + = Gdk::Pixbuf::create_from_data( + (guint8 *)pixels, + Gdk::COLORSPACE_RGB, + false, + 8, + width, + height, + 3 * width )->flip( false )-> + add_alpha(false, 0, 0, 0)->scale_simple( + resultWidth, resultHeight, + Gdk::INTERP_HYPER); + if( pixels ) + g_free( pixels ); + + return buf; + +} + +Glib::RefPtr +Histogram::get_linear_histogram( + gsize resultWidth, gsize resultHeight, + Histogram::Channel resultChannel) throw() +{ + gsize maxLevel = 1 << buffer_.bitsPerChannel_; + gsize width = maxLevel; + gsize height = maxLevel; + guint8 *pixels = g_new0( guint8, width * height * 3); + memset( pixels, 0x28, 3 * width * height ); //dark grey + + //Grid lines + for( guint32 i = 0; i < width; i += 64 ) + { + for( guint32 j = 0; j < height; j+=4 ) + { + guint8 *fill = ( pixels + ( i + j * width ) * 3 ); + fill[ RED ] = fill[ GREEN ] = fill[ BLUE ] = 0x73; + } + } + for( guint32 i = 0; i < width; i +=4 ) + { + for( guint32 j = 0; j < height; j+=64 ) + { + guint8 *fill = ( pixels + ( i + j * width ) * 3 ); + fill[ RED ] = fill[ GREEN ] = fill[ BLUE ] = 0x73; + } + } + if( !data_ ) + { + Glib::RefPtr buf + = Gdk::Pixbuf::create_from_data( + (guint8 *)pixels, + Gdk::COLORSPACE_RGB, + false, + 8, + width, + height, + 3 * width )->flip( false )-> + add_alpha(false, 0, 0, 0)->scale_simple( + resultWidth, resultHeight, + Gdk::INTERP_HYPER); + if( pixels ) + g_free( pixels ); + + return buf; + } + + for( gsize i = 0; i < maxLevel; i++ ) + { + //we have to set rgb and A for each pixel + // and we are going L2R + + //Considering we use only RGB channels + guint8 channel = 0; + guint32 maxVal = 0; + for( ; channel < 3; channel++ ) + { + double level = (double)data_[ channel ][ i ]; + guint32 normLvl = (guint32)((double)( level/maxLevel_ ) * (double)(height-1)); + maxVal = ( maxVal < normLvl ) ? normLvl : maxVal; + if( RGB == resultChannel + || channel == resultChannel ) + { + for( gsize j = 0; j <= normLvl; j++ ) + { + Pixel *fill = (Pixel *)( + pixels + (i + j * width)*3); + fill->channels_[ channel ] + |= (j + 2 > normLvl ) ? 0xFF : 0xAA; + } + } + } + + //Demarkate value channel + for(guint32 j = maxVal - ((maxVal > 0 )?1:0); + j <= maxVal; j++ ) + { + guint8 *fill = (pixels + (i + j * width)*3); + fill[ RED ] = fill[ GREEN ] = fill[ BLUE ] = 0xFF; + } + } + + Glib::RefPtr buf + = Gdk::Pixbuf::create_from_data( + (guint8 *)pixels, + Gdk::COLORSPACE_RGB, + false, + 8, + width, + height, + 3 * width )->flip( false )-> + add_alpha(false, 0, 0, 0)->scale_simple( + resultWidth, resultHeight, + Gdk::INTERP_HYPER); + if( pixels ) + g_free( pixels ); + + return buf; + +} + +void +Histogram::cleanup() +{ + max[ RED ] = max[ GREEN ] = max[ BLUE ] = 0; + maxLevel_ = 0; + if( data_ ) + { + gsize channels = buffer_.numChannels_; + for( gsize i = 0; i < channels; i++ ) + { + if( data_[ i ] ) + g_free( data_[ i ] ); + } + g_free( data_ ); + data_ = NULL; + } +} + +} //namespace Solang diff --git a/src/common/histogram.h b/src/common/histogram.h new file mode 100644 index 0000000..5043355 --- /dev/null +++ b/src/common/histogram.h @@ -0,0 +1,75 @@ +#ifndef SOLANG_HISTOGRAM_H +#define SOLANG_HISTOGRAM_H + +#include +#include "types.h" + +namespace Solang +{ + +class Histogram +{ + public: + enum Channel + { + RED = 0, + GREEN, + BLUE, + RGB, + //ALPHA, + //VALUE + }; + enum Type + { + LINEAR, + LOGARITHMIC + }; + + struct DataBuffer + { + guint8 *data_; + gsize size_; + guint8 bitsPerChannel_; + guint8 numChannels_; + gsize width_; + gsize height_; + gsize rowstride_; + }; + + Histogram( ); + ~Histogram(); + + void + createData( const DataBuffer &data ); + + Glib::RefPtr + get_pixbuf( Type type, gsize width, gsize height, + Channel channel = RGB ) throw(); + + private: + Glib::RefPtr + get_logarithmic_histogram( + gsize width, gsize height, + Channel resultChannel ) throw(); + + Glib::RefPtr + get_linear_histogram( + gsize width, gsize height, + Channel resultChannel ) throw(); + + void + cleanup(); + + struct Pixel + { + guint8 channels_[3]; + }; + guint32 **data_; + guint32 max[3]; + guint32 maxLevel_; + DataBuffer buffer_; + +}; + +} //namespace Solang +#endif //SOLANG_HISTOGRAM_H diff --git a/src/common/progress-observer.cpp b/src/common/progress-observer.cpp index 2f66b1c..ad23a34 100644 --- a/src/common/progress-observer.cpp +++ b/src/common/progress-observer.cpp @@ -75,6 +75,7 @@ ProgressObserver::set_current_events(guint64 current_events) throw() { Glib::Mutex::Lock lock(mutex_); currentEvents_ = current_events; + progress_.emit(); } void @@ -112,6 +113,7 @@ ProgressObserver::reset() throw() currentEvents_ = 0; numEvents_ = 0; stop_ = false; + progress_.emit(); } } // namespace Solang diff --git a/src/common/types.h b/src/common/types.h index d89b705..a5d241e 100644 --- a/src/common/types.h +++ b/src/common/types.h @@ -152,6 +152,8 @@ class ProgressDialog; typedef Glib::RefPtr ConstProgressDialogPtr; typedef Glib::RefPtr ProgressDialogPtr; +typedef Glib::RefPtr DispatcherPtr; + class ProgressObserver; typedef std::tr1::shared_ptr ConstProgressObserverPtr; @@ -254,6 +256,20 @@ typedef std::vector TreePathList; typedef Glib::RefPtr ConstUIManagerPtr; typedef Glib::RefPtr UIManagerPtr; +//Editing engine +class Buffer; +typedef std::tr1::shared_ptr BufferPtr; + +class EditEngine; +typedef EditEngine *EditEnginePtr; + +class Filter; +typedef std::tr1::shared_ptr FilterPtr; + +class Operation; +typedef std::tr1::shared_ptr OperationPtr; + + } // namespace Solang #endif // SOLANG_TYPES_H diff --git a/src/edit-engine/Makefile.am b/src/edit-engine/Makefile.am new file mode 100644 index 0000000..08a0eb4 --- /dev/null +++ b/src/edit-engine/Makefile.am @@ -0,0 +1,45 @@ +noinst_LTLIBRARIES = libeditengine.la + +libeditengine_la_SOURCES = \ + brightness-operation.cpp \ + brightness-operation.h \ + contrast-operation.cpp \ + contrast-operation.h \ + buffer.cpp \ + buffer.h \ + edit-types.h \ + edit-engine.h \ + edit-engine.cpp \ + filter.cpp \ + filter.h \ + flip-operation.cpp \ + flip-operation.h \ + load-file.cpp \ + load-file.h \ + operation.cpp \ + operation.h \ + scale-operation.cpp \ + scale-operation.h + +AM_CPPFLAGS = \ + -DPACKAGE_LOCALE_DIR=\""${datadir}/locale"\" \ + -DPACKAGE_SRC_DIR=\""$(srcdir)"\" \ + -DPACKAGE_DATA_DIR=\""$(datadir)"\" \ + -I$(top_builddir) \ + -I$(top_srcdir)/src/application \ + -I$(top_srcdir)/src/common \ + -I$(top_srcdir)/src/edit-engine \ + -I$(top_srcdir)/src/renderer \ + $(SOLANG_CFLAGS) \ + $(CAIROMM_CFLAGS) \ + $(EXIV2_CFLAGS) \ + $(GTKMM_CFLAGS) \ + $(GDAMM_CFLAGS) \ + $(GIOMM_CFLAGS) \ + $(GLIBMM_CFLAGS) \ + $(GDL_CFLAGS) \ + $(GEGL_CFLAGS) \ + $(SIGC_CFLAGS) + +AM_CXXFLAGS = \ + -Wall diff --git a/src/edit-engine/brightness-operation.cpp b/src/edit-engine/brightness-operation.cpp new file mode 100644 index 0000000..94d89f6 --- /dev/null +++ b/src/edit-engine/brightness-operation.cpp @@ -0,0 +1,62 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * Copyright (C) 2009 Santanu Sinha + * + * Solang 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 3 of the License, or + * (at your option) any later version. + * + * Solang 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, see . + */ + +#ifndef HAVE_CONFIG_H +#include "config.h" +#endif //HAVE_CONFIG_H + +#include +#include + +#include "edit-engine.h" +#include "brightness-operation.h" + +namespace Solang +{ + +BrightnessOperation::BrightnessOperation( const EditEnginePtr &engine, + double fraction ) + :Filter( engine ), + fraction_( fraction ) +{ + GeglNodePtr pAction = gegl_node_new_child( + get_engine()->get_root_node(), + "operation", "gegl:brightness-contrast", + "brightness", fraction, + NULL); + set_execution_node( pAction ); +} + +BrightnessOperation::~BrightnessOperation() throw() +{ +} + +Glib::ustring +BrightnessOperation::get_name() const throw() +{ + return _("Brightness"); +} + +Glib::ustring +BrightnessOperation::get_description() const throw() +{ + return _("Brighten image"); +} + + +} //namespace Solang diff --git a/src/edit-engine/brightness-operation.h b/src/edit-engine/brightness-operation.h new file mode 100644 index 0000000..f20606a --- /dev/null +++ b/src/edit-engine/brightness-operation.h @@ -0,0 +1,52 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * Copyright (C) 2009 Santanu Sinha + * + * Solang 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 3 of the License, or + * (at your option) any later version. + * + * Solang 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, see . + */ + +#include "filter.h" + +#ifndef SOLANG_BRIGHTNESS_OPERATION_H +#define SOLANG_BRIGHTNESS_OPERATION_H + +namespace Solang +{ + +class BrightnessOperation + : public Filter +{ + public: + BrightnessOperation( const EditEnginePtr &engine, + double fraction ); + + BrightnessOperation( const EditEnginePtr &engine, + const Glib::ustring &xmlPath ); + + ~BrightnessOperation() throw(); + + virtual Glib::ustring + get_name() const throw(); + + virtual Glib::ustring + get_description() const throw(); + + private: + double fraction_; +}; + + +}//namespace Solang + +#endif //SOLANG_BRIGHTNESS_OPERATION_H diff --git a/src/edit-engine/buffer.cpp b/src/edit-engine/buffer.cpp new file mode 100644 index 0000000..1854a32 --- /dev/null +++ b/src/edit-engine/buffer.cpp @@ -0,0 +1,210 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * Copyright (C) 2009 Santanu Sinha + * + * Solang 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 3 of the License, or + * (at your option) any later version. + * + * Solang 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, see . + */ + +#ifndef HAVE_CONFIG_H +#include "config.h" +#endif //HAVE_CONFIG_H + +extern "C" +{ +#include +} + +#include +#include +#include +#include +#include + +#include "buffer.h" +#include "edit-engine.h" +#include "edit-utils.h" +#include "progress-observer.h" + + +namespace Solang +{ + + +EditBits Buffer::BITS_ = EDIT_8_BITS; + +Buffer::Buffer() + :buffer_( NULL ), + refresh_() +{ +} + +Buffer::Buffer( const GeglBufferPtr &buffer ) + :buffer_( buffer ), + refresh_() +{ +} + +Buffer::Buffer( const GeglRectangle &rect ) + :buffer_( NULL ), + refresh_() +{ + buffer_ = create_buffer( rect ); +} + +Buffer::Buffer( const Buffer &rhs ) + :buffer_( rhs.buffer_ ), + refresh_() +{ +} + +Buffer::~Buffer() +{ + if( buffer_ ) + gegl_buffer_destroy( buffer_ ); + buffer_ = NULL; +} + +Buffer & +Buffer::operator =( const Buffer & rhs ) +{ + if( this != &rhs ) + { + set_buffer( rhs.buffer_ ); + } + return *this; +} + +PixbufPtr +Buffer::get_pixbuf() throw() +{ + //The steps to do this are: + //1. create Cairo surface from buffer + //2. create pixmap from surface + //3. put pixmap in pixbuf + //Step 1: + //const Babl *fmt= get_babl_format_from_cairo(); + const guint8 channels = 3; + gint width = gegl_buffer_get_width( buffer_ ); + gint height = gegl_buffer_get_height( buffer_ ); + gpointer dataBuffer = g_new0 (guint8, gegl_buffer_get_pixel_count (buffer_) * channels); + bzero( dataBuffer, gegl_buffer_get_pixel_count (buffer_) * channels); + gegl_buffer_get( buffer_, //buffer + 1.0, //scale + NULL, //extent .. we want the full thing + babl_format("RGB u8"), //color + dataBuffer, //pointer to buffer + channels * width ); //rowstride +#if 0 + Glib::RefPtr pixmap + = Gdk::Pixmap::create( + Glib::RefPtr(), + width, height, 32 ); + Cairo::RefPtr context + = pixmap->create_cairo_context(); + context->set_source( surface, 0, 0 ); + context->paint(); +#endif + std::cout<<"Here"<(dataBuffer), + //buffer + Gdk::COLORSPACE_RGB, //Colorspace + false, //has alpha channel + 8, //bits per sample + width, + height, + channels * width ); //rowstride + //= num channels * width +} + +GeglBufferPtr +Buffer::create_buffer(const GeglRectangle &rect) +{ + return gegl_buffer_new( + &rect, babl_format ( + (EDIT_16_BITS == Buffer::BITS_ ) + ?"RGB u16":"RGB u8")); +} + +void +Buffer::set_buffer( const GeglBufferPtr &buffer ) +{ + buffer_ = buffer; + refresh_.emit(); +} + +void +Buffer::open_image_file( const Glib::ustring &path, + EditEnginePtr engine ) +{ + if( buffer_ ) + { + refresh_.emit(); + return; + } + std::cout<<"Open: "<get_root_node(), + "operation", "gegl:load", + "path", path.c_str(), + NULL); + GeglRectangle rect = gegl_node_get_bounding_box( pAction ); + GeglBufferPtr pBuf = NULL; + GeglNodePtr pOut = gegl_node_new_child( + engine->get_root_node(), + "operation", "gegl:save-buffer", + "buffer", &pBuf, + NULL); + gegl_node_link_many( pAction, pOut, NULL ); + + GeglProcessor *processor + = gegl_node_new_processor (pOut, &rect); + double progress = 0.0; + ProgressObserverPtr obs = engine->get_observer(); + obs->set_num_events( 100 ); + obs->set_event_description( _("Running Filter") ); + + while ( gegl_processor_work (processor, &progress) ) + { + obs->set_current_events( progress * 100.0 ); + std::cout<<"Prog: "<get_buffer(); + const GeglRectangle *extent + = gegl_buffer_get_extent( pBuf ); + gegl_buffer_save( pBuf, path.c_str(), extent ); + return; +} + +BufferPtr +Buffer::deserialize( const Glib::ustring &path ) throw(Error) +{ + GeglBufferPtr pBuf = gegl_buffer_load( path.c_str() ); + return BufferPtr( new Buffer( pBuf ) ); +} + +} //namespace Solang diff --git a/src/edit-engine/buffer.h b/src/edit-engine/buffer.h new file mode 100644 index 0000000..0e65add --- /dev/null +++ b/src/edit-engine/buffer.h @@ -0,0 +1,100 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * Copyright (C) 2009 Santanu Sinha + * + * Solang 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 3 of the License, or + * (at your option) any later version. + * + * Solang 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, see . + */ + +#ifndef SOLANG_BUFFER_H +#define SOLANG_BUFFER_H + +#include +#include + +#include "edit-types.h" +#include "error.h" +#include "types.h" + +namespace Solang +{ + +class Buffer +{ + public: + Buffer(); + Buffer( const GeglBufferPtr &buffer ); + Buffer( const GeglRectangle & rect ); + Buffer( const Buffer &rhs ); + ~Buffer(); + + Buffer & + operator=( const Buffer &rhs ); + + PixbufPtr + get_pixbuf() throw(); + + inline GeglBufferPtr + get_buffer() throw(); + + void + set_buffer( const GeglBufferPtr &buffer ); + + inline Glib::Dispatcher & + get_refresh() throw(); + + void + open_image_file( const Glib::ustring &path, + EditEnginePtr engine ); + + inline bool + is_empty() const throw(); + + static void + serialize(const BufferPtr &buffer, + const Glib::ustring &path) throw(Error); + static BufferPtr + deserialize(const Glib::ustring &path) throw(Error); + + private: + GeglBufferPtr + create_buffer(const GeglRectangle &rect); + + static EditBits BITS_; + + GeglBufferPtr buffer_; + + Glib::Dispatcher refresh_; +}; + +inline GeglBufferPtr +Buffer::get_buffer() throw() +{ + return buffer_; +} + +inline Glib::Dispatcher & +Buffer::get_refresh() throw() +{ + return refresh_; +} + +inline bool +Buffer::is_empty() const throw() +{ + return NULL == buffer_; +} + +} //namespace solang + +#endif //SOLANG_BUFFER_H diff --git a/src/edit-engine/contrast-operation.cpp b/src/edit-engine/contrast-operation.cpp new file mode 100644 index 0000000..9eb22c1 --- /dev/null +++ b/src/edit-engine/contrast-operation.cpp @@ -0,0 +1,63 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * Copyright (C) 2009 Santanu Sinha + * + * Solang 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 3 of the License, or + * (at your option) any later version. + * + * Solang 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, see . + */ + +#ifndef HAVE_CONFIG_H +#include "config.h" +#endif //HAVE_CONFIG_H + +#include +#include + +#include "edit-engine.h" +#include "contrast-operation.h" + +namespace Solang +{ + +ContrastOperation::ContrastOperation( const EditEnginePtr &engine, + double contrast ) + :Filter( engine ), + contrast_( contrast ) +{ + GeglNodePtr pAction = gegl_node_new_child( + get_engine()->get_root_node(), + "operation", "gegl:brightness-contrast", + "brightness", 0.0, + "contrast", 1.0 + contrast, + NULL); + set_execution_node( pAction ); +} + +ContrastOperation::~ContrastOperation() throw() +{ +} + +Glib::ustring +ContrastOperation::get_name() const throw() +{ + return _("Contrast"); +} + +Glib::ustring +ContrastOperation::get_description() const throw() +{ + return _("Change image contrast"); +} + + +} //namespace Solang diff --git a/src/edit-engine/contrast-operation.h b/src/edit-engine/contrast-operation.h new file mode 100644 index 0000000..5abdfe7 --- /dev/null +++ b/src/edit-engine/contrast-operation.h @@ -0,0 +1,52 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * Copyright (C) 2009 Santanu Sinha + * + * Solang 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 3 of the License, or + * (at your option) any later version. + * + * Solang 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, see . + */ + +#include "filter.h" + +#ifndef SOLANG_CONTRAST_OPERATION_H +#define SOLANG_CONTRAST_OPERATION_H + +namespace Solang +{ + +class ContrastOperation + : public Filter +{ + public: + ContrastOperation( const EditEnginePtr &engine, + double contrast ); + + ContrastOperation( const EditEnginePtr &engine, + const Glib::ustring &xmlPath ); + + ~ContrastOperation() throw(); + + virtual Glib::ustring + get_name() const throw(); + + virtual Glib::ustring + get_description() const throw(); + + private: + double contrast_; +}; + + +}//namespace Solang + +#endif //SOLANG_CONTRAST_OPERATION_H diff --git a/src/edit-engine/desaturate-operation.cpp b/src/edit-engine/desaturate-operation.cpp new file mode 100644 index 0000000..11ec43d --- /dev/null +++ b/src/edit-engine/desaturate-operation.cpp @@ -0,0 +1,64 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * Copyright (C) 2009 Santanu Sinha + * + * Solang 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 3 of the License, or + * (at your option) any later version. + * + * Solang 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, see . + */ + +#ifndef HAVE_CONFIG_H +#include "config.h" +#endif //HAVE_CONFIG_H + +#include +#include + +#include "edit-engine.h" +#include "desaturate-operation.h" + +namespace Solang +{ + +DesaturateOperation::DesaturateOperation( const EditEnginePtr &engine, + double fraction ) + :Filter( engine ), + fraction_( fraction ) +{ + GeglNodePtr pAction = gegl_node_new_child( + get_engine()->get_root_node(), + "operation", "gegl:desaturate", + "filter", "cubic", + "x", fraction, + "y", fraction, + NULL); + set_execution_node( pAction ); +} + +DesaturateOperation::~DesaturateOperation() throw() +{ +} + +Glib::ustring +DesaturateOperation::get_name() const throw() +{ + return _("Desaturate"); +} + +Glib::ustring +DesaturateOperation::get_description() const throw() +{ + return _("Desaturate image"); +} + + +} //namespace Solang diff --git a/src/edit-engine/desaturate-operation.h b/src/edit-engine/desaturate-operation.h new file mode 100644 index 0000000..41c51a8 --- /dev/null +++ b/src/edit-engine/desaturate-operation.h @@ -0,0 +1,52 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * Copyright (C) 2009 Santanu Sinha + * + * Solang 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 3 of the License, or + * (at your option) any later version. + * + * Solang 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, see . + */ + +#include "filter.h" + +#ifndef SOLANG_SCALE_OPERATION_H +#define SOLANG_SCALE_OPERATION_H + +namespace Solang +{ + +class ScaleOperation + : public Filter +{ + public: + ScaleOperation( const EditEnginePtr &engine, + double fraction ); + + ScaleOperation( const EditEnginePtr &engine, + const Glib::ustring &xmlPath ); + + ~ScaleOperation() throw(); + + virtual Glib::ustring + get_name() const throw(); + + virtual Glib::ustring + get_description() const throw(); + + private: + double fraction_; +}; + + +}//namespace Solang + +#endif //SOLANG_SCALE_OPERATION_H diff --git a/src/edit-engine/edit-engine.cpp b/src/edit-engine/edit-engine.cpp new file mode 100644 index 0000000..ff411dd --- /dev/null +++ b/src/edit-engine/edit-engine.cpp @@ -0,0 +1,89 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * Copyright (C) 2009 Santanu Sinha + * + * Solang 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 3 of the License, or + * (at your option) any later version. + * + * Solang 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, see . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif //HAVE_CONFIG_H + +#include + +#include "edit-engine.h" +#include "operation.h" + +namespace Solang +{ + +EditEngine::EditEngine() + :observer_(), + rootNode_( NULL ) +{ +} + +EditEngine::~EditEngine() throw() +{ + if( NULL != rootNode_ ) + { + final(); + } +} + +void +EditEngine::init( const ProgressObserverPtr &observer ) throw() +{ + observer_ = observer; + //rootNode_ = gegl_node_new(); +} + +BufferPtr +EditEngine::apply( OperationPtr &op ) throw(Error) +try +{ + return op->apply( observer_ ); +} +catch(Error &e) +{ + e.add_call_info( __FUNCTION__, __FILE__, __LINE__ ); + throw; +} + +BufferPtr +EditEngine::revert( OperationPtr &op ) throw(Error) +try +{ + return op->revert( observer_ ); +} +catch(Error &e) +{ + e.add_call_info( __FUNCTION__, __FILE__, __LINE__ ); + throw; +} + +void +EditEngine::final() throw() +{ + g_object_unref( rootNode_ ); + rootNode_ = NULL; +} + +void +EditEngine::set_root_node( GeglNodePtr root ) throw() +{ + rootNode_ = root; +} + +} //namespace Solang diff --git a/src/edit-engine/edit-engine.h b/src/edit-engine/edit-engine.h new file mode 100644 index 0000000..684ff41 --- /dev/null +++ b/src/edit-engine/edit-engine.h @@ -0,0 +1,77 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * Copyright (C) 2009 Santanu Sinha + * + * Solang 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 3 of the License, or + * (at your option) any later version. + * + * Solang 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, see . + */ + +#ifndef SOLANG_EDIT_ENGINE_H +#define SOLANG_EDIT_ENGINE_H + +#include "error.h" +#include "edit-types.h" +#include "non-copyable.h" +#include "types.h" + +namespace Solang +{ + +class EditEngine + : public NonCopyable +{ + public: + EditEngine(); + ~EditEngine() throw(); + + void + init(const ProgressObserverPtr &observer) throw(); + + BufferPtr + apply( OperationPtr &op ) throw(Error); + + BufferPtr + revert( OperationPtr &op ) throw(Error); + + void + final() throw(); + + inline GeglNodePtr + get_root_node() throw(); + + void + set_root_node( GeglNodePtr root ) throw(); + + inline ProgressObserverPtr + get_observer() throw(); + + private: + ProgressObserverPtr observer_; + GeglNodePtr rootNode_; +}; + +inline ProgressObserverPtr +EditEngine::get_observer() throw() +{ + return observer_; +} + +inline GeglNodePtr +EditEngine::get_root_node() throw() +{ + return rootNode_; +} + +} //namespace Solang + +#endif //SOLANG_EDIT_ENGINE_H diff --git a/src/edit-engine/edit-types.h b/src/edit-engine/edit-types.h new file mode 100644 index 0000000..ab6ef8b --- /dev/null +++ b/src/edit-engine/edit-types.h @@ -0,0 +1,41 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * Copyright (C) 2009 Santanu Sinha + * + * Solang 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 3 of the License, or + * (at your option) any later version. + * + * Solang 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, see . + */ + +#ifndef SOLANG_EDIT_TYPES_H +#define SOLANG_EDIT_TYPES_H + +#include +#include + +namespace Solang +{ + +enum EditBits +{ + EDIT_16_BITS = 0, + EDIT_8_BITS +}; + + +//Gegl +typedef GeglNode * GeglNodePtr; +typedef GeglBuffer * GeglBufferPtr; + +} //namespace Solang + +#endif //SOLANG_EDIT_TYPES_H diff --git a/src/edit-engine/edit-utils.h b/src/edit-engine/edit-utils.h new file mode 100644 index 0000000..f07dd6c --- /dev/null +++ b/src/edit-engine/edit-utils.h @@ -0,0 +1,45 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * Copyright (C) 2009 Santanu Sinha + * + * Solang 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 3 of the License, or + * (at your option) any later version. + * + * Solang 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, see . + */ + +extern "C" +{ +#include +} + +inline Babl *get_babl_format_from_cairo() +{ + //The following code is taken from nipce + //Copyright (C) 2008-2009 Hubert Figuiere + return babl_format_new(babl_model("R'G'B'A"), + babl_type ("u8"), +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + babl_component ("B'"), + babl_component ("G'"), + babl_component ("R'"), + babl_component ("A"), +#elif G_BYTE_ORDER == G_BIG_ENDIAN + babl_component ("A"), + babl_component ("R'"), + babl_component ("G'"), + babl_component ("B'"), +#else +#error unknown endian +#endif + NULL); + +} diff --git a/src/edit-engine/filter.cpp b/src/edit-engine/filter.cpp new file mode 100644 index 0000000..b26d022 --- /dev/null +++ b/src/edit-engine/filter.cpp @@ -0,0 +1,76 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * Copyright (C) 2009 Santanu Sinha + * + * Solang 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 3 of the License, or + * (at your option) any later version. + * + * Solang 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, see . + */ +#include +#include + +#include "edit-engine.h" +#include "filter.h" + +namespace Solang +{ +Filter::Filter( const EditEnginePtr &engine ) + :node_( NULL ), + engine_( engine ) +{ +} + +Filter::Filter( const EditEnginePtr &engine, + const Glib::ustring &xmlPath ) + :node_( NULL ), + engine_( NULL ) +{ + node_ = gegl_node_new_from_file( xmlPath.c_str() ); +} + +Filter::~Filter() throw() +{ + //Auto deleted by reference counting + g_object_unref( node_ ); +} + +void +Filter::dumpXml( const Glib::ustring &path ) +{ + std::ofstream fout( path.c_str() ); + GeglNode *pInput = gegl_node_get_input_proxy( + engine_->get_root_node(), + "proxy-input"); + gegl_node_connect_to( pInput, "proc", node_, "inp"); + GeglNode *pOutput = gegl_node_get_output_proxy( + engine_->get_root_node(), + "proxy-output"); + gegl_node_connect_to( node_, "outp", pOutput, "inp-proc"); + //gegl_node_link_many( pInput, node_, pOutput, NULL ); + char buf[ BUFSIZ ]; + gegl_node_to_xml( pOutput, buf ); + fout< + * + * Solang 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 3 of the License, or + * (at your option) any later version. + * + * Solang 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, see . + */ + +#ifndef SOLANG_FILTER_H +#define SOLANG_FILTER_H + +#include + +#include "non-copyable.h" +#include "edit-types.h" + +namespace Solang +{ + +class Filter + : public NonCopyable +{ + protected: + Filter( const EditEnginePtr &engine ); + Filter( const EditEnginePtr &engine, + const Glib::ustring &xmlPath ); + + public: + virtual ~Filter() throw(); + + virtual void + dumpXml( const Glib::ustring &path ); + + inline GeglNodePtr + get_execution_node(); + + inline EditEnginePtr + get_engine(); + + void + set_execution_node( GeglNodePtr node ); + + virtual Glib::ustring + get_name() const throw() = 0; + + virtual Glib::ustring + get_description() const throw() = 0; + + private: + GeglNodePtr node_; + EditEnginePtr engine_; +}; + +inline GeglNodePtr +Filter::get_execution_node() +{ + return node_; +} +inline EditEnginePtr +Filter::get_engine() +{ + return engine_; +} + +} // namespace Solang +#endif //SOLANG_FILTER_H diff --git a/src/edit-engine/flip-operation.cpp b/src/edit-engine/flip-operation.cpp new file mode 100644 index 0000000..728c19e --- /dev/null +++ b/src/edit-engine/flip-operation.cpp @@ -0,0 +1,64 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * Copyright (C) 2009 Santanu Sinha + * + * Solang 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 3 of the License, or + * (at your option) any later version. + * + * Solang 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, see . + */ + +#ifndef HAVE_CONFIG_H +#include "config.h" +#endif //HAVE_CONFIG_H + +#include +#include + +#include "edit-engine.h" +#include "flip-operation.h" + +namespace Solang +{ + +FlipOperation::FlipOperation( const EditEnginePtr &engine, + const FlipOperation::Direction direction ) + :Filter( engine ), + direction_( direction ) +{ + std::string axis = ( HORIZONTAL == direction ) + ? "y" : "x"; + GeglNodePtr pAction = gegl_node_new_child( + get_engine()->get_root_node(), + "operation", "gegl:reflect", + axis.c_str(), 1.0, + NULL); + set_execution_node( pAction ); +} + +FlipOperation::~FlipOperation() throw() +{ +} + +Glib::ustring +FlipOperation::get_name() const throw() +{ + return _("Flip"); +} + +Glib::ustring +FlipOperation::get_description() const throw() +{ + return _("Flip image"); +} + + +} //namespace Solang diff --git a/src/edit-engine/flip-operation.h b/src/edit-engine/flip-operation.h new file mode 100644 index 0000000..9f91d61 --- /dev/null +++ b/src/edit-engine/flip-operation.h @@ -0,0 +1,59 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * Copyright (C) 2009 Santanu Sinha + * + * Solang 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 3 of the License, or + * (at your option) any later version. + * + * Solang 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, see . + */ + +#include "filter.h" + +#ifndef SOLANG_FLIP_OPERATION_H +#define SOLANG_FLIP_OPERATION_H + +namespace Solang +{ + +class FlipOperation + : public Filter +{ + public: + enum Direction + { + HORIZONTAL, + VERTICAL + }; + + public: + FlipOperation( const EditEnginePtr &engine, + const Direction direction); + + FlipOperation( const EditEnginePtr &engine, + const Glib::ustring &xmlPath ); + + ~FlipOperation() throw(); + + virtual Glib::ustring + get_name() const throw(); + + virtual Glib::ustring + get_description() const throw(); + + private: + Direction direction_; +}; + + +}//namespace Solang + +#endif //SOLANG_FLIP_OPERATION_H diff --git a/src/edit-engine/load-file.cpp b/src/edit-engine/load-file.cpp new file mode 100644 index 0000000..2c8b5df --- /dev/null +++ b/src/edit-engine/load-file.cpp @@ -0,0 +1,61 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * Copyright (C) 2009 Santanu Sinha + * + * Solang 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 3 of the License, or + * (at your option) any later version. + * + * Solang 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, see . + */ + +#ifndef HAVE_CONFIG_H +#include "config.h" +#endif //HAVE_CONFIG_H + +#include +#include + +#include "edit-engine.h" +#include "load-file.h" + +namespace Solang +{ + +LoadFile::LoadFile( const EditEnginePtr &engine, + const char *path ) + :Filter( engine ) +{ + GeglNodePtr pAction = gegl_node_new_child( + get_engine()->get_root_node(), + "operation", "gegl:load", + "path", path, + NULL); + set_execution_node( pAction ); +} + +LoadFile::~LoadFile() throw() +{ +} + +Glib::ustring +LoadFile::get_name() const throw() +{ + return _("Load Image"); +} + +Glib::ustring +LoadFile::get_description() const throw() +{ + return _("Load image file for editing"); +} + + +} //namespace Solang diff --git a/src/edit-engine/load-file.h b/src/edit-engine/load-file.h new file mode 100644 index 0000000..3f87f5c --- /dev/null +++ b/src/edit-engine/load-file.h @@ -0,0 +1,50 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * Copyright (C) 2009 Santanu Sinha + * + * Solang 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 3 of the License, or + * (at your option) any later version. + * + * Solang 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, see . + */ + +#include "filter.h" + +#ifndef SOLANG_LOAD_FILE_H +#define SOLANG_LOAD_FILE_H + +namespace Solang +{ + +class LoadFile + : public Filter +{ + public: + LoadFile( const EditEnginePtr &engine, + const char *path); + + LoadFile( const EditEnginePtr &engine, + const Glib::ustring &xmlPath ); + + ~LoadFile() throw(); + + virtual Glib::ustring + get_name() const throw(); + + virtual Glib::ustring + get_description() const throw(); + +}; + + +}//namespace Solang + +#endif //SOLANG_LOAD_FILE_H diff --git a/src/edit-engine/operation.cpp b/src/edit-engine/operation.cpp new file mode 100644 index 0000000..a814f38 --- /dev/null +++ b/src/edit-engine/operation.cpp @@ -0,0 +1,107 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * Copyright (C) 2009 Santanu Sinha + * + * Solang 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 3 of the License, or + * (at your option) any later version. + * + * Solang 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, see . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif //HAVE_CONFIG_H + +#include +#include +#include + +#include "buffer.h" +#include "edit-engine.h" +#include "filter.h" +#include "operation.h" +#include "progress-observer.h" + +namespace Solang +{ +Operation::Operation( + const EditEnginePtr &engine, + const FilterPtr &filter, + const BufferPtr &buffer ) + :engine_( engine ), + filter_( filter ), + original_( buffer ) +{ +} + +Operation::~Operation() throw() +{ +} + +BufferPtr +Operation::apply( + const ProgressObserverPtr &observer) throw(Error) +{ + GeglBufferPtr pBuf = gegl_buffer_dup( + original_->get_buffer() ); + GeglNodePtr pRoot = engine_->get_root_node(); + if( !pRoot ) + { + pRoot = gegl_node_new(); + engine_->set_root_node( pRoot ); + } + GeglNodePtr pInp = gegl_node_new_child( pRoot, + "operation", "gegl:load-buffer", + "buffer", pBuf, + NULL); + GeglRectangle rect = gegl_node_get_bounding_box( pInp ); + GeglNodePtr pAction = filter_->get_execution_node(); + GeglBufferPtr pOutBuf = NULL; + GeglNodePtr pOut = gegl_node_new_child( pRoot, + "operation", "gegl:save-buffer", + "buffer", &pOutBuf, + NULL ); + gegl_node_link_many( pInp, pAction, pOut, NULL ); + + //Now process + GeglProcessor *processor + = gegl_node_new_processor (pOut, NULL); + double progress = 0.0; + observer->set_num_events( 100 ); + observer->set_event_description( _("Running Filter") ); + + while ( gegl_processor_work (processor, &progress) ) + { + observer->set_current_events( progress * 100.0 ); + observer->progress().emit(); + std::cout<<"Done:"<set_root_node( NULL ); + //original_.reset(); + + return BufferPtr( new Buffer( pOutBuf ) ); + +} + +BufferPtr +Operation::revert( + const ProgressObserverPtr &observer) throw(Error) +{ + return original_; +} + +} //namespace Solang diff --git a/src/edit-engine/operation.h b/src/edit-engine/operation.h new file mode 100644 index 0000000..5b50b76 --- /dev/null +++ b/src/edit-engine/operation.h @@ -0,0 +1,53 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * Copyright (C) 2009 Santanu Sinha + * + * Solang 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 3 of the License, or + * (at your option) any later version. + * + * Solang 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, see . + */ + +#include "edit-types.h" +#include "error.h" +#include "non-copyable.h" + +#ifndef SOLANG_OPERATION_H +#define SOLANG_OPERATION_H + +namespace Solang +{ + +class Operation + :public NonCopyable +{ + public: + Operation( + const EditEnginePtr &engine, + const FilterPtr &filter, + const BufferPtr &buffer ); + + ~Operation() throw(); + + BufferPtr + apply( const ProgressObserverPtr &observer) throw(Error); + + BufferPtr + revert( const ProgressObserverPtr &observer) throw(Error); + + private: + EditEnginePtr engine_; + FilterPtr filter_; + BufferPtr original_; +}; + +} //namespace Solang +#endif //SOLANG_OPERATION_H diff --git a/src/edit-engine/scale-operation.cpp b/src/edit-engine/scale-operation.cpp new file mode 100644 index 0000000..68ddb42 --- /dev/null +++ b/src/edit-engine/scale-operation.cpp @@ -0,0 +1,64 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * Copyright (C) 2009 Santanu Sinha + * + * Solang 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 3 of the License, or + * (at your option) any later version. + * + * Solang 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, see . + */ + +#ifndef HAVE_CONFIG_H +#include "config.h" +#endif //HAVE_CONFIG_H + +#include +#include + +#include "edit-engine.h" +#include "scale-operation.h" + +namespace Solang +{ + +ScaleOperation::ScaleOperation( const EditEnginePtr &engine, + double fraction ) + :Filter( engine ), + fraction_( fraction ) +{ + GeglNodePtr pAction = gegl_node_new_child( + get_engine()->get_root_node(), + "operation", "gegl:scale", + "filter", "cubic", + "x", fraction, + "y", fraction, + NULL); + set_execution_node( pAction ); +} + +ScaleOperation::~ScaleOperation() throw() +{ +} + +Glib::ustring +ScaleOperation::get_name() const throw() +{ + return _("Scale"); +} + +Glib::ustring +ScaleOperation::get_description() const throw() +{ + return _("Scale image"); +} + + +} //namespace Solang diff --git a/src/edit-engine/scale-operation.h b/src/edit-engine/scale-operation.h new file mode 100644 index 0000000..41c51a8 --- /dev/null +++ b/src/edit-engine/scale-operation.h @@ -0,0 +1,52 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * Copyright (C) 2009 Santanu Sinha + * + * Solang 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 3 of the License, or + * (at your option) any later version. + * + * Solang 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, see . + */ + +#include "filter.h" + +#ifndef SOLANG_SCALE_OPERATION_H +#define SOLANG_SCALE_OPERATION_H + +namespace Solang +{ + +class ScaleOperation + : public Filter +{ + public: + ScaleOperation( const EditEnginePtr &engine, + double fraction ); + + ScaleOperation( const EditEnginePtr &engine, + const Glib::ustring &xmlPath ); + + ~ScaleOperation() throw(); + + virtual Glib::ustring + get_name() const throw(); + + virtual Glib::ustring + get_description() const throw(); + + private: + double fraction_; +}; + + +}//namespace Solang + +#endif //SOLANG_SCALE_OPERATION_H diff --git a/src/editor/Makefile.am b/src/editor/Makefile.am index 76fc909..8f78ac2 100644 --- a/src/editor/Makefile.am +++ b/src/editor/Makefile.am @@ -1,20 +1,44 @@ noinst_LTLIBRARIES = libeditor.la libeditor_la_SOURCES = \ + brightness-widget.cpp \ + brightness-widget.h \ + contrast-widget.cpp \ + contrast-widget.h \ + desaturate.cpp \ + desaturate.h \ + desaturate-widget.cpp \ + desaturate-widget.h \ edit-action.cpp \ edit-action.h \ edit-action-history.cpp \ edit-action-history.h \ + edit-action-widget.cpp \ + edit-action-widget.h \ editable-photo.cpp \ editable-photo.h \ + editor-toolbar.cpp \ + editor-toolbar.h \ editor.cpp \ editor.h \ flip.cpp \ flip.h \ + flip-widget.cpp \ + flip-widget.h \ + gegl-operation.cpp \ + gegl-operation.h \ + rotate-widget.cpp \ + rotate-widget.h \ rotate.cpp \ rotate.h \ save-photos-window.cpp \ - save-photos-window.h + save-photos-window.h \ + scale.cpp \ + scale.h \ + scale-widget.cpp \ + scale-widget.h \ + stock-button.cpp \ + stock-button.h AM_CPPFLAGS = \ -DPACKAGE_LOCALE_DIR=\""${datadir}/locale"\" \ @@ -25,6 +49,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/attribute \ -I$(top_srcdir)/src/common \ -I$(top_srcdir)/src/database \ + -I$(top_srcdir)/src/edit-engine \ -I$(top_srcdir)/src/editor \ -I$(top_srcdir)/src/importer \ -I$(top_srcdir)/src/renderer \ @@ -36,7 +61,8 @@ AM_CPPFLAGS = \ $(GIOMM_CFLAGS) \ $(GLIBMM_CFLAGS) \ $(GDL_CFLAGS) \ - $(SIGC_CFLAGS) + $(SIGC_CFLAGS) \ + $(GEGL_CFLAGS) AM_CXXFLAGS = \ -Wall diff --git a/src/editor/brightness-widget.cpp b/src/editor/brightness-widget.cpp new file mode 100644 index 0000000..0a1e09f --- /dev/null +++ b/src/editor/brightness-widget.cpp @@ -0,0 +1,62 @@ +#ifndef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "application.h" +#include "editable-photo.h" +#include "editor-toolbar.h" +#include "editor.h" +#include "gegl-operation.h" +#include "operation.h" +#include "brightness-operation.h" +#include "brightness-widget.h" + +namespace Solang +{ + +BrightnessWidget::BrightnessWidget( EditorToolbar &toolbar, + Editor &editor) + :EditActionWidget( _("Brightness"), toolbar, editor ), + brightness_(-100.0, 100.1, 0.1), + hbFraction_(), + engine_() +{ + //hbDir_.pack_start( lblDirection_, Gtk::PACK_SHRINK, 6); + hbFraction_.pack_start( brightness_, Gtk::PACK_EXPAND_WIDGET, 6 ); + hbFraction_.pack_end( btApply_, Gtk::PACK_SHRINK, 0 ); + add( hbFraction_ ); + + brightness_.set_increments( 0.1, 0.5 ); + brightness_.set_update_policy( Gtk::UPDATE_DELAYED ); + brightness_.set_value( 0.0 ); + connection_ = btApply_.signal_clicked() + .connect( sigc::mem_fun( *this, + &EditActionWidget::on_apply_clicked ) ); + + return; +} + +BrightnessWidget::~BrightnessWidget() +{ +} + +EditActionPtr +BrightnessWidget::get_action() +{ + double fraction = brightness_.get_value(); + FilterPtr filter( new BrightnessOperation( + editor_.get_engine(), fraction / 100 ) ); + BufferPtr buffer = editor_.get_current_photo() + ->get_edit_buffer(); + OperationPtr op( new Operation( + editor_.get_engine(), + filter, buffer ) ); + return EditActionPtr( new GeglOperation( op, + editor_.get_application() + ->get_engine().get_default_observer() ) ); + +} + +}//namespace Solang diff --git a/src/editor/brightness-widget.h b/src/editor/brightness-widget.h new file mode 100644 index 0000000..9a2fcde --- /dev/null +++ b/src/editor/brightness-widget.h @@ -0,0 +1,33 @@ +#ifndef SOLANG_BRIGHTNESS_WIDGET_H +#define SOLANG_BRIGHTNESS_WIDGET_H + +#include +#include "edit-action-widget.h" + +namespace Solang +{ +class EditorToolbar; + +class BrightnessWidget + : public EditActionWidget +{ + public: + BrightnessWidget( EditorToolbar &toolbar, + Editor &editor ); + ~BrightnessWidget(); + + protected: + + virtual EditActionPtr + get_action(); + + private: + Gtk::HScale brightness_; + Gtk::HBox hbFraction_; + EditEnginePtr engine_; +}; + +} + + +#endif //SOLANG_BRIGHTNESS_WIDGET_H diff --git a/src/editor/contrast-widget.cpp b/src/editor/contrast-widget.cpp new file mode 100644 index 0000000..57a74d4 --- /dev/null +++ b/src/editor/contrast-widget.cpp @@ -0,0 +1,63 @@ +#ifndef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "application.h" +#include "editable-photo.h" +#include "editor-toolbar.h" +#include "editor.h" +#include "gegl-operation.h" +#include "operation.h" +#include "contrast-operation.h" +#include "contrast-widget.h" + +namespace Solang +{ + +ContrastWidget::ContrastWidget( EditorToolbar &toolbar, + Editor &editor) + :EditActionWidget( _("Contrast"), toolbar, editor ), + contrast_(-100.0, 100.1, 0.1), + hbFraction_(), + engine_() +{ + //hbDir_.pack_start( lblDirection_, Gtk::PACK_SHRINK, 6); + hbFraction_.pack_start( contrast_, Gtk::PACK_EXPAND_WIDGET, 6 ); + hbFraction_.pack_end( btApply_, Gtk::PACK_SHRINK, 0 ); + add( hbFraction_ ); + + contrast_.set_increments( 0.1, 0.5 ); + contrast_.set_update_policy( Gtk::UPDATE_DELAYED ); + contrast_.set_value( 0.0 ); + connection_ = btApply_.signal_clicked() + .connect( sigc::mem_fun( *this, + &EditActionWidget::on_apply_clicked ) ); + + + return; +} + +ContrastWidget::~ContrastWidget() +{ +} + +EditActionPtr +ContrastWidget::get_action() +{ + double contrast = contrast_.get_value(); + FilterPtr filter( new ContrastOperation( + editor_.get_engine(), contrast / 100 ) ); + BufferPtr buffer = editor_.get_current_photo() + ->get_edit_buffer(); + OperationPtr op( new Operation( + editor_.get_engine(), + filter, buffer ) ); + return EditActionPtr( new GeglOperation( op, + editor_.get_application() + ->get_engine().get_default_observer() ) ); + +} + +}//namespace Solang diff --git a/src/editor/contrast-widget.h b/src/editor/contrast-widget.h new file mode 100644 index 0000000..8ce0464 --- /dev/null +++ b/src/editor/contrast-widget.h @@ -0,0 +1,33 @@ +#ifndef SOLANG_CONTRAST_WIDGET_H +#define SOLANG_CONTRAST_WIDGET_H + +#include +#include "edit-action-widget.h" + +namespace Solang +{ +class EditorToolbar; + +class ContrastWidget + : public EditActionWidget +{ + public: + ContrastWidget( EditorToolbar &toolbar, + Editor &editor ); + ~ContrastWidget(); + + protected: + + virtual EditActionPtr + get_action(); + + private: + Gtk::HScale contrast_; + Gtk::HBox hbFraction_; + EditEnginePtr engine_; +}; + +} + + +#endif //SOLANG_CONTRAST_WIDGET_H diff --git a/src/editor/desaturate-widget.cpp b/src/editor/desaturate-widget.cpp new file mode 100644 index 0000000..0f25390 --- /dev/null +++ b/src/editor/desaturate-widget.cpp @@ -0,0 +1,52 @@ +#ifndef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "application.h" +#include "editable-photo.h" +#include "editor-toolbar.h" +#include "editor.h" +#include "gegl-operation.h" +#include "operation.h" +#include "desaturate.h" +#include "desaturate-widget.h" + +namespace Solang +{ + +DesaturateWidget::DesaturateWidget( EditorToolbar &toolbar, + Editor &editor) + :EditActionWidget( _("Saturation"), toolbar, editor ), + fraction_(-100.0, 100.0, 1.0), + hbFraction_(), + engine_() +{ + //hbDir_.pack_start( lblDirection_, Gtk::PACK_SHRINK, 6); + hbFraction_.pack_start( fraction_, Gtk::PACK_EXPAND_WIDGET, 6 ); + hbFraction_.pack_end( btApply_, Gtk::PACK_SHRINK, 0 ); + add( hbFraction_ ); + + fraction_.set_increments( 1.0, 5.0 ); + fraction_.set_update_policy( Gtk::UPDATE_CONTINUOUS ); + fraction_.set_value( 0.0 ); + connection_ = btApply_.signal_clicked() + .connect( sigc::mem_fun( *this, + &EditActionWidget::on_apply_clicked ) ); + + return; +} + +DesaturateWidget::~DesaturateWidget() +{ +} + +EditActionPtr +DesaturateWidget::get_action() +{ + double fraction = 1.0 + ( fraction_.get_value() / 100 ); + return EditActionPtr( new Desaturate( fraction ) ); +} + +}//namespace Solang diff --git a/src/editor/desaturate-widget.h b/src/editor/desaturate-widget.h new file mode 100644 index 0000000..3818d84 --- /dev/null +++ b/src/editor/desaturate-widget.h @@ -0,0 +1,33 @@ +#ifndef SOLANG_DESATURATE_WIDGET_H +#define SOLANG_DESATURATE_WIDGET_H + +#include +#include "edit-action-widget.h" + +namespace Solang +{ +class EditorToolbar; + +class DesaturateWidget + : public EditActionWidget +{ + public: + DesaturateWidget( EditorToolbar &toolbar, + Editor &editor ); + ~DesaturateWidget(); + + protected: + + virtual EditActionPtr + get_action(); + + private: + Gtk::HScale fraction_; + Gtk::HBox hbFraction_; + EditEnginePtr engine_; +}; + +} + + +#endif //SOLANG_DESATURATE_WIDGET_H diff --git a/src/editor/desaturate.cpp b/src/editor/desaturate.cpp new file mode 100644 index 0000000..949df33 --- /dev/null +++ b/src/editor/desaturate.cpp @@ -0,0 +1,88 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * Copyright (C) 2009 Santanu Sinha + * + * Solang 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 3 of the License, or + * (at your option) any later version. + * + * Solang 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, see . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "editable-photo.h" +#include "desaturate.h" + +namespace Solang +{ + +Desaturate::Desaturate( double fraction ) + :EditAction(), + fraction_( fraction ), + oldBuf_() +{ +} + +Desaturate::~Desaturate() throw() +{ +} + +void +Desaturate::execute( EditablePhoto &photo) throw(Error) +{ + try + { + oldBuf_ = photo.get_buffer(); + PixbufPtr dest = oldBuf_->copy(); + photo.get_buffer()->saturate_and_pixelate( dest, + fraction_, false ); + photo.set_buffer( dest ); + PixbufPtr thumb = photo.get_photo()->get_thumbnail_buffer(); + if( thumb ) + { + int width = thumb->get_width(); + int height = thumb->get_height(); + photo.get_photo()->set_thumbnail_buffer( + dest->scale_simple( + width, height, Gdk::INTERP_NEAREST ) ); + } + } + catch( Error &e ) + { + e.add_call_info( __FUNCTION__, __FILE__, __LINE__ ); + throw; + } +} + +void +Desaturate::reverse( EditablePhoto &photo ) throw(Error) +{ + PixbufPtr thumb = photo.get_photo()->get_thumbnail_buffer(); + if( thumb ) + { + int width = thumb->get_width(); + int height = thumb->get_height(); + photo.get_photo()->set_thumbnail_buffer( + oldBuf_->scale_simple( + width, height, Gdk::INTERP_NEAREST ) ); + } + photo.set_buffer( oldBuf_ ); + return; + +} + +} //namespace Solang diff --git a/src/editor/desaturate.h b/src/editor/desaturate.h new file mode 100644 index 0000000..03970b4 --- /dev/null +++ b/src/editor/desaturate.h @@ -0,0 +1,48 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * Copyright (C) 2009 Santanu Sinha + * + * Solang 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 3 of the License, or + * (at your option) any later version. + * + * Solang 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, see . + */ + +#ifndef SOLANG_DESATURATE_H +#define SOLANG_DESATURATE_H + +#include "edit-action.h" + +namespace Solang +{ + +class Desaturate : + public EditAction +{ + public: + Desaturate( double fraction ); + virtual ~Desaturate() throw(); + + virtual void + execute( EditablePhoto &photo) throw(Error); + + virtual void + reverse( EditablePhoto &photo) throw(Error); + + private: + double fraction_; + PixbufPtr oldBuf_; + +}; + +} //namespace Solang + +#endif // SOLANG_DESATURATE_H diff --git a/src/editor/edit-action-widget.cpp b/src/editor/edit-action-widget.cpp new file mode 100644 index 0000000..fd8bf5f --- /dev/null +++ b/src/editor/edit-action-widget.cpp @@ -0,0 +1,36 @@ +#include "edit-action-widget.h" +#include "editor-toolbar.h" + +namespace Solang +{ + +EditActionWidget::EditActionWidget( + const Glib::ustring &label, + EditorToolbar &toolBar, + Editor &editor ) + : Gtk::Expander( label ), + btApply_( Gtk::Stock::APPLY ), + signalApplyClicked_( toolBar.signal_apply() ), + connection_(), + editor_( editor ) +{ +// connection_ = btApply_.signal_clicked().connect( +// sigc::mem_fun( *this, +// &EditActionWidget::on_apply_clicked ) ); + btApply_.set_relief( Gtk::RELIEF_NONE ); +} + +EditActionWidget::~EditActionWidget() +{ + connection_.disconnect(); +} + +void +EditActionWidget::on_apply_clicked() +{ + signalApplyClicked_.emit( get_action() ); +} + + +} //namespace Solang + diff --git a/src/editor/edit-action-widget.h b/src/editor/edit-action-widget.h new file mode 100644 index 0000000..470c90b --- /dev/null +++ b/src/editor/edit-action-widget.h @@ -0,0 +1,39 @@ +#ifndef SOLANG_EDIT_ACTION_WIDGET_H +#define SOLANG_EDIT_ACTION_WIDGET_H + +#include +#include "editor-toolbar.h" +#include "stock-button.h" +#include "types.h" + +namespace Solang +{ + +class Editor; + +class EditActionWidget + : public Gtk::Expander +{ + public: + EditActionWidget( const Glib::ustring &label, + EditorToolbar &toolBar, + Editor &editor ); + virtual ~EditActionWidget(); + + void + on_apply_clicked(); + + protected: + virtual EditActionPtr + get_action() = 0; + + protected: + StockButton btApply_; + EditorToolbar::ActionSignal &signalApplyClicked_; + sigc::connection connection_; + Editor &editor_; +}; + +} //namespace Solang + +#endif //SOLANG_EDIT_ACTION_WIDGET_H diff --git a/src/editor/editable-photo.cpp b/src/editor/editable-photo.cpp index 3531516..4c62eb7 100644 --- a/src/editor/editable-photo.cpp +++ b/src/editor/editable-photo.cpp @@ -20,11 +20,18 @@ #include "config.h" #endif -#include +extern "C" +{ +#include +} + +#include +#include #include #include +#include "buffer.h" #include "edit-action.h" #include "editable-photo.h" @@ -34,6 +41,8 @@ namespace Solang EditablePhoto::EditablePhoto( const PhotoPtr &photo ) throw() :photo_( photo ), buffer_( 0 ), + editBuffer_( ), + isDirty_( false ), image_(), toSave_( false ) { @@ -51,14 +60,39 @@ EditablePhoto::set_photo( const PhotoPtr &photo ) throw() setup_photo_for_edit(); } +const PixbufPtr +EditablePhoto::get_buffer() const throw() +{ +#ifdef FULL_GEGL + if( !editBuffer_->is_empty() + && isDirty_ ) + { + buffer_ = editBuffer_->get_pixbuf(); + isDirty_ = false; + } +#endif + return buffer_; +} + void -EditablePhoto::set_buffer(const PixbufPtr &buffer ) +EditablePhoto::set_buffer(const PixbufPtr &buffer, bool sync ) { buffer_ = buffer; // if( photo_->get_buffer() ) { photo_->set_buffer( buffer_ ); } + if( sync && editBuffer_ && !isDirty_ ) + { + editBuffer_ = pixbuf_to_edit_buffer(); + } +} + +void +EditablePhoto::set_edit_buffer( const BufferPtr &buffer ) throw() +{ + editBuffer_ = buffer; + //isDirty_ = true; } void @@ -122,6 +156,7 @@ EditablePhoto::setup_photo_for_edit( ) throw() buffer_ = loader->get_pixbuf(); #endif +//CREATE buffer_ = photo_->get_buffer(); if( ! buffer_ ) { @@ -193,4 +228,27 @@ EditablePhoto::redo_last_action( ) throw(Error) } } +BufferPtr +EditablePhoto::pixbuf_to_edit_buffer() throw() +{ + bool hasAlpha = buffer_->get_has_alpha(); + const guint8 channels = 3;//(hasAlpha)?4:3; + GeglRectangle rect; + rect.width = buffer_->get_width(); + rect.height = buffer_->get_height(); + rect.x = rect.y = 0; + Babl *fmt = babl_format( "RGB u8" ); + //(hasAlpha) ?"RGBA u8" : "RGB u8" ); + size_t size = rect.width * rect.height *channels; + gpointer pMem = g_new0( guint8, size ); + ::memcpy( pMem, (void *)(buffer_->get_pixels()), size ); + GeglBufferPtr gBuf = gegl_buffer_new( &rect, fmt ); + gegl_buffer_set( gBuf, //gegl buffer + &rect, //extent + fmt, //format + pMem, + buffer_->get_rowstride() ); + return BufferPtr ( new Buffer( gBuf ) ); +} + } //namespace Solang diff --git a/src/editor/editable-photo.h b/src/editor/editable-photo.h index 6d2bb97..63c439f 100644 --- a/src/editor/editable-photo.h +++ b/src/editor/editable-photo.h @@ -61,11 +61,17 @@ class EditablePhoto void set_photo( const PhotoPtr & ) throw(); - inline const PixbufPtr & + const PixbufPtr get_buffer() const throw(); void - set_buffer(const PixbufPtr &); + set_buffer(const PixbufPtr &, bool sync = true); + + inline const BufferPtr + get_edit_buffer() throw(); + + void + set_edit_buffer( const BufferPtr &buffer ) throw(); inline Exiv2::ExifData & //Modifiable get_exif_data() throw(); @@ -96,8 +102,13 @@ class EditablePhoto void setup_photo_for_edit() throw(); + BufferPtr + pixbuf_to_edit_buffer() throw(); + PhotoPtr photo_; - PixbufPtr buffer_; + mutable PixbufPtr buffer_; + mutable BufferPtr editBuffer_; + mutable bool isDirty_; Exiv2::Image::AutoPtr image_; bool toSave_; EditActionHistory appliedActions_; @@ -109,10 +120,16 @@ EditablePhoto::get_photo() const throw() return photo_; } -inline const PixbufPtr & -EditablePhoto::get_buffer() const throw() +inline const BufferPtr +EditablePhoto::get_edit_buffer() throw() { - return buffer_; +#if 0 + if( !editBuffer_ ) + { + editBuffer_ = pixbuf_to_edit_buffer(); + } +#endif + return pixbuf_to_edit_buffer(); } inline Exiv2::ExifData & //Modifiable diff --git a/src/editor/editor-toolbar.cpp b/src/editor/editor-toolbar.cpp new file mode 100644 index 0000000..0575759 --- /dev/null +++ b/src/editor/editor-toolbar.cpp @@ -0,0 +1,52 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif //HAVE_CONFIG_H + +#include + +#include "edit-action-widget.h" +#include "editor-toolbar.h" + +namespace Solang +{ +EditorToolbar::EditorToolbar() + :ScrolledWindow(), + filters_(), + histogramExpander_( _("Histogram") ), + histoGram_(), + widgets_() +{ + set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); + Gtk::ScrolledWindow::add(filters_); + filters_.pack_start( histogramExpander_, Gtk::PACK_SHRINK, 6 ); + histogramExpander_.add( histoGram_ ); + histogramExpander_.set_expanded( true ); +} + +EditorToolbar::~EditorToolbar() +{ +} + +void +EditorToolbar::add( + const Glib::RefPtr &widget ) +{ + widgets_.push_back( widget ); + return; +} + +void +EditorToolbar::setup() throw() +{ + for( WidgetList::iterator widget = widgets_.begin(); + widget != widgets_.end(); widget++ ) + { + Glib::RefPtr editWidget = *widget; + filters_.pack_start( + *(editWidget.operator ->()), Gtk::PACK_SHRINK, 6 ); + } +} + +} //namespace Solang + + diff --git a/src/editor/editor-toolbar.h b/src/editor/editor-toolbar.h new file mode 100644 index 0000000..82c1a8f --- /dev/null +++ b/src/editor/editor-toolbar.h @@ -0,0 +1,58 @@ +#ifndef SOLANG_EDITOR_TOOLBAR_H +#define SOLANG_EDITOR_TOOLBAR_H + +#include +#include "histogram-viewer.h" + +namespace Solang +{ + +class EditActionWidget; + +class EditorToolbar + : public Gtk::ScrolledWindow +{ + public: + typedef sigc::signal ActionSignal; + typedef std::vector > WidgetList; + public: + + EditorToolbar(); + + ~EditorToolbar(); + + inline HistogramViewer & + get_histogram_viewer(); + + inline ActionSignal & + signal_apply(); + + void + add( const Glib::RefPtr &widget ); + + void + setup() throw(); + + private: + Gtk::VBox filters_; + Gtk::Expander histogramExpander_; + HistogramViewer histoGram_; + ActionSignal signalApply_; + WidgetList widgets_; +}; + +inline HistogramViewer & +EditorToolbar::get_histogram_viewer() +{ + return histoGram_; +} + +inline EditorToolbar::ActionSignal & +EditorToolbar::signal_apply() +{ + return signalApply_; +} + + +} //namespace Solang +#endif //SOLANG_EDITOR_TOOLBAR_H diff --git a/src/editor/editor.cpp b/src/editor/editor.cpp index cba0916..4da2beb 100644 --- a/src/editor/editor.cpp +++ b/src/editor/editor.cpp @@ -22,13 +22,19 @@ #include #include +#include #include "application.h" +#include "buffer.h" +#include "cursor-changer.h" #include "edit-action.h" +#include "edit-engine.h" #include "editable-photo.h" #include "editor.h" #include "flip.h" +#include "gegl-operation.h" #include "main-window.h" +#include "operation.h" #include "rotate.h" #include "save-photos-window.h" @@ -62,7 +68,8 @@ Editor::Editor( ) iconFactory_( Gtk::IconFactory::create()), uiID_( 0 ), actionPerformed_(), - currentPhoto_() + currentPhoto_(), + engine_( NULL ) { Gtk::IconSource icon_source; @@ -107,7 +114,7 @@ Editor::Editor( ) Gtk::Action::create( "ActionEditMenu", _("_Edit"))); - actionGroup_->add( + actionGroup_->add( Gtk::Action::create( "ActionEditUndo", Gtk::Stock::UNDO, @@ -116,7 +123,7 @@ Editor::Editor( ) Gtk::AccelKey("z"), sigc::mem_fun(*this, &Editor::on_action_undo)); - actionGroup_->add( + actionGroup_->add( Gtk::Action::create( "ActionEditRedo", Gtk::Stock::REDO, @@ -134,7 +141,7 @@ Editor::Editor( ) Gtk::AccelKey(""), sigc::mem_fun(*this, &Editor::on_action_flip_horz)); - actionGroup_->add( + actionGroup_->add( Gtk::Action::create( "ActionEditFlipVertical", Gtk::StockID(PACKAGE_TARNAME"-flip-vert"), @@ -143,7 +150,7 @@ Editor::Editor( ) Gtk::AccelKey(""), sigc::mem_fun(*this, &Editor::on_action_flip_vert)); - actionGroup_->add( + actionGroup_->add( Gtk::Action::create( "ActionEditRotateClockwise", Gtk::StockID(PACKAGE_TARNAME"-rotate-right"), @@ -152,7 +159,7 @@ Editor::Editor( ) Gtk::AccelKey(""), sigc::mem_fun(*this, &Editor::on_action_rotate_right)); - actionGroup_->add( + actionGroup_->add( Gtk::Action::create( "ActionEditRotateCounterClockwise", Gtk::StockID(PACKAGE_TARNAME"-rotate-left"), @@ -161,7 +168,7 @@ Editor::Editor( ) Gtk::AccelKey(""), sigc::mem_fun(*this, &Editor::on_action_rotate_left)); - actionGroup_->add( + actionGroup_->add( Gtk::Action::create( "ActionEditScale", Gtk::StockID(PACKAGE_TARNAME"-scale"), @@ -170,13 +177,14 @@ Editor::Editor( ) Gtk::AccelKey(""), sigc::mem_fun(*this, &Editor::on_action_scale)); - actionGroup_->add( + actionGroup_->add( Gtk::Action::create( "ActionEditSaveAs", Gtk::Stock::SAVE, _("_Save")), Gtk::AccelKey(""), sigc::mem_fun(*this, &Editor::on_action_save)); + } Editor::~Editor() throw() @@ -211,7 +219,13 @@ Editor::apply( const EditActionPtr &action, void Editor::apply( const EditActionPtr &action) { - apply( action, currentPhoto_ ); + Glib::ThreadPool & thread_pool + = application_->get_thread_pool(); + thread_pool.push(sigc::bind( + sigc::mem_fun2( *this, + &Editor::apply_action), + action, currentPhoto_ )); + //apply( action, currentPhoto_ ); } void @@ -229,6 +243,8 @@ void Editor::init( Application &app ) { application_ = &app; + engine_ = new EditEngine(); + engine_->init( application_->get_engine().get_default_observer() ); } void @@ -268,6 +284,7 @@ void Editor::final( Application &app ) { unregister_ui(); + delete engine_; } void @@ -311,6 +328,44 @@ void Editor::set_current_photo( const EditablePhotoPtr &photo ) { currentPhoto_ = photo; + + if( !currentPhoto_ ) + return; + +#if 0 + buffer->open_image_file( + photo->get_photo()->get_disk_file_path(), + engine_); +#endif + +#ifdef SS_LATER + Glib::ThreadPool & thread_pool + = application_->get_thread_pool(); + thread_pool.push(sigc::bind( + sigc::mem_fun2( *(photo->get_edit_buffer()), + &Buffer::open_image_file), + photo->get_photo()->get_disk_file_path(), + engine_ )); +#endif + +#if 0 + Glib::Thread * const loader = Glib::Thread::create( + sigc::bind( + sigc::mem_fun2( *buffer, + &Buffer::open_image_file), + photo->get_photo()->get_disk_file_path(), + engine_ ), true ); + loader->join(); +#endif + return; +} + +void +Editor::apply_action( const EditActionPtr &action, + const EditablePhotoPtr &photo ) throw() +{ + CursorChanger tmp( application_->get_main_window() ); + apply( action, photo ); } void @@ -318,11 +373,32 @@ Editor::on_action_flip_horz() throw() { EditActionPtr action( new Flip( true ) ); apply( action ); + +#if 0 + FilterPtr filter( new FlipOperation( engine_, + FlipOperation::HORIZONTAL ) ); + BufferPtr buffer = currentPhoto_->get_edit_buffer(); + OperationPtr op( new Operation( + engine_, filter, buffer ) ); + EditActionPtr action( new GeglOperation( op, + application_->get_engine().get_default_observer() ) ); + apply( action ); +#endif } void Editor::on_action_flip_vert() throw() { +#if 0 + FilterPtr filter( new FlipOperation( engine_, + FlipOperation::VERTICAL) ); + BufferPtr buffer = currentPhoto_->get_edit_buffer(); + OperationPtr op( new Operation( + engine_, filter, buffer ) ); + EditActionPtr action( new GeglOperation( op, + application_->get_engine().get_default_observer() ) ); + apply( action ); +#endif EditActionPtr action( new Flip( false ) ); apply( action ); } @@ -357,6 +433,7 @@ Editor::on_action_save() throw() void Editor::on_action_undo() throw() { + CursorChanger tmp( application_->get_main_window() ); if( !currentPhoto_ ) { return; @@ -368,6 +445,7 @@ Editor::on_action_undo() throw() void Editor::on_action_redo() throw() { + CursorChanger tmp( application_->get_main_window() ); if( !currentPhoto_ ) { return; diff --git a/src/editor/editor.h b/src/editor/editor.h index 8d6810c..6b98350 100644 --- a/src/editor/editor.h +++ b/src/editor/editor.h @@ -64,9 +64,18 @@ class Editor inline Glib::Dispatcher & edit_action_performed() throw(); + inline EditEnginePtr & + get_engine() throw(); + + inline EditablePhotoPtr + get_current_photo() throw(); + void set_current_photo( const EditablePhotoPtr &photo ); + inline ApplicationPtr + get_application() throw(); + private: void @@ -102,6 +111,10 @@ class Editor void on_action_paste_actions() throw(); + void + apply_action( const EditActionPtr &action, + const EditablePhotoPtr &photo ) throw(); + ApplicationPtr application_; EditablePhotoList modifiedPhotos_; Glib::Mutex mutex_; @@ -111,6 +124,7 @@ class Editor Glib::Dispatcher actionPerformed_; EditablePhotoPtr currentPhoto_; EditActionList copiedActions_; + EditEnginePtr engine_; }; inline Glib::Dispatcher & @@ -119,6 +133,24 @@ Editor::edit_action_performed() throw() return actionPerformed_; } +inline EditEnginePtr & +Editor::get_engine() throw() +{ + return engine_; +} + +inline EditablePhotoPtr +Editor::get_current_photo() throw() +{ + return currentPhoto_; +} + +inline ApplicationPtr +Editor::get_application() throw() +{ + return application_; +} + } //namespace solang #endif diff --git a/src/editor/flip-widget.cpp b/src/editor/flip-widget.cpp new file mode 100644 index 0000000..972400b --- /dev/null +++ b/src/editor/flip-widget.cpp @@ -0,0 +1,63 @@ +#ifndef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "editor-toolbar.h" +#include "flip-widget.h" +#include "flip.h" + +namespace Solang +{ + +FlipWidget::FlipWidget( EditorToolbar &toolbar, + Editor &editor ) + :EditActionWidget( _("Flip"), toolbar, editor ), + columns_(), + dirStore_( Gtk::ListStore::create( columns_ )), + cmbDirection_(), + hbDir_() +{ + //hbDir_.pack_start( lblDirection_, Gtk::PACK_SHRINK, 6); + hbDir_.pack_start( cmbDirection_, Gtk::PACK_EXPAND_WIDGET, 6 ); +// hbDir_.pack_start( btApply_ ); + add( hbDir_ ); + + cmbDirection_.set_model( dirStore_ ); + cmbDirection_.pack_start( columns_.name_ ); + { + //Directions + Gtk::TreeModel::Row row = *(dirStore_->append()); + row[ columns_.direction_ ] = true; + row[ columns_.name_ ] = _("Horizontal"); + } + { + //Directions + Gtk::TreeModel::Row row = *(dirStore_->append()); + row[ columns_.direction_ ] = false; + row[ columns_.name_ ] = _("Vertical"); + } + //cmbDirection_.set_active( 0 ); + connection_ = cmbDirection_.signal_changed().connect( + sigc::mem_fun( *this, + &EditActionWidget::on_apply_clicked ) ); + + return; +} + +FlipWidget::~FlipWidget() +{ +} + +EditActionPtr +FlipWidget::get_action() +{ + Gtk::TreeModel::const_iterator dirI + = cmbDirection_.get_active(); + Gtk::TreeModel::Row dirR = (*dirI); + bool direction = dirR[ columns_.direction_ ]; + return EditActionPtr( new Flip( direction ) ); +} + +}//namespace Solang diff --git a/src/editor/flip-widget.h b/src/editor/flip-widget.h new file mode 100644 index 0000000..976e7ab --- /dev/null +++ b/src/editor/flip-widget.h @@ -0,0 +1,49 @@ +#ifndef SOLANG_FLIP_WIDGET_H +#define SOLANG_FLIP_WIDGET_H + +#include +#include "stock-button.h" +#include "edit-action-widget.h" +#include "rotate.h" + +namespace Solang +{ +class EditorToolbar; + +class FlipWidget + : public EditActionWidget +{ + private: + class DirectionSelectionColumns + : public Gtk::TreeModel::ColumnRecord + { + public: + DirectionSelectionColumns() + { + add( direction_ ); + add( name_ ); + } + Gtk::TreeModelColumn direction_; + Gtk::TreeModelColumn name_; + }; + public: + FlipWidget( EditorToolbar &toolbar, + Editor &editor ); + ~FlipWidget(); + + protected: + + virtual EditActionPtr + get_action(); + + private: + DirectionSelectionColumns columns_; + Glib::RefPtr dirStore_; + Gtk::ComboBox cmbDirection_; + Gtk::HBox hbDir_; +}; + +} + + +#endif //SOLANG_FLIP_WIDGET_H diff --git a/src/editor/gegl-operation.cpp b/src/editor/gegl-operation.cpp new file mode 100644 index 0000000..79d4216 --- /dev/null +++ b/src/editor/gegl-operation.cpp @@ -0,0 +1,94 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * Copyright (C) 2009 Santanu Sinha + * + * Solang 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 3 of the License, or + * (at your option) any later version. + * + * Solang 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, see . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + +#include "buffer.h" +#include "editable-photo.h" +#include "gegl-operation.h" +#include "operation.h" + +namespace Solang +{ + +GeglOperation::GeglOperation( const OperationPtr &operation, + const ProgressObserverPtr &observer ) + :EditAction(), + operation_( operation ), + oldBuf_(), + newBuf_(), + observer_( observer ) +{ +} + +GeglOperation::~GeglOperation() throw() +{ +} + +void +GeglOperation::execute( EditablePhoto &photo) throw(Error) +{ + if( !newBuf_ ) + { + oldBuf_ = photo.get_buffer(); + BufferPtr geglBuf = operation_->apply( observer_ ); + //photo.set_edit_buffer( newBuf ); + PixbufPtr outBuf = geglBuf->get_pixbuf(); + newBuf_ = outBuf; + operation_.reset(); + } + photo.set_buffer( newBuf_, false ); + PixbufPtr thumb = photo.get_photo()->get_thumbnail_buffer(); + if( thumb ) + { + int width = thumb->get_width(); + int height = thumb->get_height(); + thumb = newBuf_->scale_simple( + width, height, Gdk::INTERP_NEAREST ); + photo.get_photo()->set_thumbnail_buffer( thumb ); + } +} + +void +GeglOperation::reverse( EditablePhoto &photo) throw(Error) +{ +#if 0 + BufferPtr newBuf = operation_->revert( observer_ ); + photo.set_edit_buffer( newBuf ); + PixbufPtr outBuf = newBuf->get_pixbuf(); + photo.set_buffer( outBuf, false ); +#endif + photo.set_buffer( oldBuf_, false ); + PixbufPtr thumb = photo.get_photo()->get_thumbnail_buffer(); + if( thumb ) + { + int width = thumb->get_width(); + int height = thumb->get_height(); + thumb = oldBuf_->scale_simple( + width, height, Gdk::INTERP_NEAREST ); + photo.get_photo()->set_thumbnail_buffer( thumb ); + } +} + +} //namespace Solang diff --git a/src/editor/gegl-operation.h b/src/editor/gegl-operation.h new file mode 100644 index 0000000..8620bec --- /dev/null +++ b/src/editor/gegl-operation.h @@ -0,0 +1,51 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * Copyright (C) 2009 Santanu Sinha + * + * Solang 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 3 of the License, or + * (at your option) any later version. + * + * Solang 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, see . + */ + +#ifndef SOLANG_GEGL_OPERATION_H +#define SOLANG_GEGL_OPERATION_H + +#include "edit-action.h" +#include "types.h" + +namespace Solang +{ + +class GeglOperation : + public EditAction +{ + public: + GeglOperation( const OperationPtr &operation, + const ProgressObserverPtr &observer ); + virtual ~GeglOperation() throw(); + + virtual void + execute( EditablePhoto &photo) throw(Error); + + virtual void + reverse( EditablePhoto &photo) throw(Error); + + private: + OperationPtr operation_; + PixbufPtr oldBuf_; + PixbufPtr newBuf_; + ProgressObserverPtr observer_; +}; + +} //namespace Solang + +#endif // SOLANG_GEGL_OPERATION_H diff --git a/src/editor/rotate-widget.cpp b/src/editor/rotate-widget.cpp new file mode 100644 index 0000000..0323f98 --- /dev/null +++ b/src/editor/rotate-widget.cpp @@ -0,0 +1,63 @@ +#ifndef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "editor-toolbar.h" +#include "rotate-widget.h" +#include "rotate.h" + +namespace Solang +{ + +RotateWidget::RotateWidget( EditorToolbar &toolbar, + Editor &editor ) + :EditActionWidget( _("Rotate"), toolbar, editor ), + columns_(), + dirStore_( Gtk::ListStore::create( columns_ )), + cmbDirection_(), + hbDir_() +{ + //hbDir_.pack_start( lblDirection_, Gtk::PACK_SHRINK, 6); + hbDir_.pack_start( cmbDirection_, Gtk::PACK_EXPAND_WIDGET, 6 ); + //hbDir_.pack_start( btApply_ ); + add( hbDir_ ); + + cmbDirection_.set_model( dirStore_ ); + cmbDirection_.pack_start( columns_.name_ ); + { + //Directions + Gtk::TreeModel::Row row = *(dirStore_->append()); + row[ columns_.direction_ ] = Rotate::ROTATE_CLOCKWISE; + row[ columns_.name_ ] = _("Clockwise"); + } + { + //Directions + Gtk::TreeModel::Row row = *(dirStore_->append()); + row[ columns_.direction_ ] = Rotate::ROTATE_COUNTERCLOCKWISE; + row[ columns_.name_ ] = _("Counter-Clockwise"); + } + //cmbDirection_.set_active( 0 ); + connection_ = cmbDirection_.signal_changed().connect( + sigc::mem_fun( *this, + &EditActionWidget::on_apply_clicked ) ); + + return; +} + +RotateWidget::~RotateWidget() +{ +} + +EditActionPtr +RotateWidget::get_action() +{ + Gtk::TreeModel::const_iterator dirI + = cmbDirection_.get_active(); + Gtk::TreeModel::Row dirR = (*dirI); + Rotate::Direction direction = dirR[ columns_.direction_ ]; + return EditActionPtr( new Rotate( direction ) ); +} + +}//namespace Solang diff --git a/src/editor/rotate-widget.h b/src/editor/rotate-widget.h new file mode 100644 index 0000000..6b75339 --- /dev/null +++ b/src/editor/rotate-widget.h @@ -0,0 +1,49 @@ +#ifndef SOLANG_ROTATE_WIDGET_H +#define SOLANG_ROTATE_WIDGET_H + +#include +#include "stock-button.h" +#include "edit-action-widget.h" +#include "rotate.h" + +namespace Solang +{ +class EditorToolbar; + +class RotateWidget + : public EditActionWidget +{ + private: + class DirectionSelectionColumns + : public Gtk::TreeModel::ColumnRecord + { + public: + DirectionSelectionColumns() + { + add( direction_ ); + add( name_ ); + } + Gtk::TreeModelColumn direction_; + Gtk::TreeModelColumn name_; + }; + public: + RotateWidget( EditorToolbar &toolbar, + Editor &editor ); + ~RotateWidget(); + + protected: + + virtual EditActionPtr + get_action(); + + private: + DirectionSelectionColumns columns_; + Glib::RefPtr dirStore_; + Gtk::ComboBox cmbDirection_; + Gtk::HBox hbDir_; +}; + +} + + +#endif //SOLANG_ROTATE_WIDGET_H diff --git a/src/editor/scale-widget.cpp b/src/editor/scale-widget.cpp new file mode 100644 index 0000000..0edd287 --- /dev/null +++ b/src/editor/scale-widget.cpp @@ -0,0 +1,52 @@ +#ifndef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "application.h" +#include "editable-photo.h" +#include "editor-toolbar.h" +#include "editor.h" +#include "gegl-operation.h" +#include "operation.h" +#include "scale.h" +#include "scale-widget.h" + +namespace Solang +{ + +ScaleWidget::ScaleWidget( EditorToolbar &toolbar, + Editor &editor) + :EditActionWidget( _("Scale"), toolbar, editor ), + fraction_(0, 201.0, 1.0), + hbFraction_(), + engine_() +{ + //hbDir_.pack_start( lblDirection_, Gtk::PACK_SHRINK, 6); + hbFraction_.pack_start( fraction_, Gtk::PACK_EXPAND_WIDGET, 6 ); + hbFraction_.pack_end( btApply_, Gtk::PACK_SHRINK, 0 ); + add( hbFraction_ ); + + fraction_.set_increments( 1.0, 10.0 ); + fraction_.set_update_policy( Gtk::UPDATE_CONTINUOUS ); + fraction_.set_value( 100.0 ); + connection_ = btApply_.signal_clicked() + .connect( sigc::mem_fun( *this, + &EditActionWidget::on_apply_clicked ) ); + + return; +} + +ScaleWidget::~ScaleWidget() +{ +} + +EditActionPtr +ScaleWidget::get_action() +{ + double fraction = fraction_.get_value(); + return EditActionPtr( new Scale( fraction / 100.0 ) ); +} + +}//namespace Solang diff --git a/src/editor/scale-widget.h b/src/editor/scale-widget.h new file mode 100644 index 0000000..6dfae5c --- /dev/null +++ b/src/editor/scale-widget.h @@ -0,0 +1,33 @@ +#ifndef SOLANG_SCALE_WIDGET_H +#define SOLANG_SCALE_WIDGET_H + +#include +#include "edit-action-widget.h" + +namespace Solang +{ +class EditorToolbar; + +class ScaleWidget + : public EditActionWidget +{ + public: + ScaleWidget( EditorToolbar &toolbar, + Editor &editor ); + ~ScaleWidget(); + + protected: + + virtual EditActionPtr + get_action(); + + private: + Gtk::HScale fraction_; + Gtk::HBox hbFraction_; + EditEnginePtr engine_; +}; + +} + + +#endif //SOLANG_SCALE_WIDGET_H diff --git a/src/editor/scale.cpp b/src/editor/scale.cpp new file mode 100644 index 0000000..4084db3 --- /dev/null +++ b/src/editor/scale.cpp @@ -0,0 +1,70 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * Copyright (C) 2009 Santanu Sinha + * + * Solang 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 3 of the License, or + * (at your option) any later version. + * + * Solang 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, see . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "editable-photo.h" +#include "scale.h" + +namespace Solang +{ + +Scale::Scale( double fraction ) + :EditAction(), + fraction_( fraction ), + oldBuf_() +{ +} + +Scale::~Scale() throw() +{ +} + +void +Scale::execute( EditablePhoto &photo) throw(Error) +{ + try + { + oldBuf_ = photo.get_buffer(); + PixbufPtr dest = oldBuf_->scale_simple( + oldBuf_->get_width() * fraction_, + oldBuf_->get_height() * fraction_, + Gdk::INTERP_HYPER); + photo.set_buffer( dest ); + } + catch( Error &e ) + { + e.add_call_info( __FUNCTION__, __FILE__, __LINE__ ); + throw; + } +} + +void +Scale::reverse( EditablePhoto &photo ) throw(Error) +{ + photo.set_buffer( oldBuf_ ); + return; +} + +} //namespace Solang diff --git a/src/editor/scale.h b/src/editor/scale.h new file mode 100644 index 0000000..400ca41 --- /dev/null +++ b/src/editor/scale.h @@ -0,0 +1,48 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * Copyright (C) 2009 Santanu Sinha + * + * Solang 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 3 of the License, or + * (at your option) any later version. + * + * Solang 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, see . + */ + +#ifndef SOLANG_SCALE_H +#define SOLANG_SCALE_H + +#include "edit-action.h" + +namespace Solang +{ + +class Scale : + public EditAction +{ + public: + Scale( double fraction ); + virtual ~Scale() throw(); + + virtual void + execute( EditablePhoto &photo) throw(Error); + + virtual void + reverse( EditablePhoto &photo) throw(Error); + + private: + double fraction_; + PixbufPtr oldBuf_; + +}; + +} //namespace Solang + +#endif // SOLANG_SCALE_H diff --git a/src/editor/stock-button.cpp b/src/editor/stock-button.cpp new file mode 100644 index 0000000..5a83a0f --- /dev/null +++ b/src/editor/stock-button.cpp @@ -0,0 +1,21 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif //HAVE_CONFIG_H + +#include "stock-button.h" + +namespace Solang +{ + +StockButton::StockButton( const Gtk::StockID &stockID ) + :Gtk::Button(), + image_( stockID, Gtk::ICON_SIZE_BUTTON ) +{ + add( image_ ); +} + +StockButton::~StockButton() +{ +} + +} //namespace Solang diff --git a/src/editor/stock-button.h b/src/editor/stock-button.h new file mode 100644 index 0000000..5bcb756 --- /dev/null +++ b/src/editor/stock-button.h @@ -0,0 +1,22 @@ +#ifndef SOLANG_STOCK_BUTTON_H +#define SOLANG_STOCK_BUTTON_H + +#include + +namespace Solang +{ + +class StockButton + : public Gtk::Button +{ + public: + StockButton(const Gtk::StockID &stockID ); + ~StockButton(); + + private: + Gtk::Image image_; +}; + +} //namespace Solang + +#endif //SOLANG_STOCK_BUTTON_H diff --git a/src/renderer/Makefile.am b/src/renderer/Makefile.am index 0bd31fa..b398a24 100644 --- a/src/renderer/Makefile.am +++ b/src/renderer/Makefile.am @@ -36,6 +36,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/common \ -I$(top_srcdir)/src/database \ -I$(top_srcdir)/src/editor \ + -I$(top_srcdir)/src/edit-engine \ -I$(top_srcdir)/src/importer \ -I$(top_srcdir)/src/renderer \ -I$(top_srcdir)/src/storage \ @@ -48,6 +49,8 @@ AM_CPPFLAGS = \ $(GIOMM_CFLAGS) \ $(GLIBMM_CFLAGS) \ $(GDL_CFLAGS) \ + $(BABL_CFLAGS) \ + $(GEGL_CFLAGS) \ $(SIGC_CFLAGS) AM_CXXFLAGS = \ diff --git a/src/renderer/editor-renderer.cpp b/src/renderer/editor-renderer.cpp index 24edc0c..65415be 100644 --- a/src/renderer/editor-renderer.cpp +++ b/src/renderer/editor-renderer.cpp @@ -25,12 +25,15 @@ #include #include #include +#include #include "application.h" #include "browser-model-column-record.h" +#include "buffer.h" #include "editable-photo.h" #include "editor-renderer.h" #include "engine.h" +#include "histogram.h" #include "i-plugin.h" #include "i-renderer-selector.h" #include "main-window.h" @@ -40,9 +43,32 @@ #include "thumbnail.h" #include "types.h" +//WIDGETS +#include "brightness-widget.h" +#include "contrast-widget.h" +#include "desaturate-widget.h" +#include "flip-widget.h" +#include "rotate-widget.h" +#include "scale-widget.h" + + namespace Solang { +PixbufPtr +scale_buffer( const PixbufPtr &src ) +{ + const guint8 width = 64; //Will change on orientation + const guint8 height = 48; + guint8 pictWidth = src->get_width(); + guint8 pictHeight = src->get_height(); + return src->scale_simple( height + * ( static_cast(pictWidth) + / static_cast(pictHeight) ) + , height, Gdk::INTERP_NEAREST ); +} + + static const std::string uiFile = PACKAGE_DATA_DIR"/"PACKAGE_TARNAME"/ui/" PACKAGE_TARNAME"-editor-renderer.ui"; @@ -76,6 +102,7 @@ EditorRenderer::EditorRenderer() throw() : editor_(), dockItem_(NULL), vPane_(), + hPane_(), imageView_(0), imageScrollWin_(0), imagesArea_( false, 6 ), @@ -343,15 +370,15 @@ EditorRenderer::EditorRenderer() throw() : { return; } - gtk_paned_pack1( GTK_PANED( vPane_.gobj() ), imageScrollWin_, - TRUE, FALSE ); + gtk_box_pack_start( GTK_BOX( vPane_.gobj() ), imageScrollWin_, + TRUE, TRUE, 6 ); gtk_widget_show_all(GTK_WIDGET(imageScrollWin_)); } btPrev_.add( left_ ); btPrev_.set_relief( Gtk::RELIEF_NONE ); imagesArea_.pack_start( btPrev_, Gtk::PACK_SHRINK, 2 ); - vPane_.pack2( imagesArea_, false, true ); - editablePhotosView_.set_size_request( -1, 100 ); + //imagesArea_.set_size_request( -1, 128 ); + editablePhotosView_.set_size_request( iconWindow_.get_width(), 48 ); // editablePhotosView_.set_item_height( 100 ); // editablePhotosView_.set_pixbuf_column( columns_.buffer_ ); editablePhotosView_.set_model( photosModel_ ); @@ -365,7 +392,7 @@ EditorRenderer::EditorRenderer() throw() : gtk_cell_layout_set_attributes( iconLayout, renderer, "pixbuf", 0, NULL ); - iconRenderer_.property_height().set_value( 100 ); + iconRenderer_.property_height().set_value( 48 ); editablePhotosView_.set_orientation( Gtk::ORIENTATION_HORIZONTAL); editablePhotosView_.set_selection_mode( Gtk::SELECTION_SINGLE ); @@ -374,20 +401,23 @@ EditorRenderer::EditorRenderer() throw() : editablePhotosView_.set_column_spacing( 8 ); editablePhotosView_.set_has_tooltip( false ); + iconWindow_.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_NEVER); iconWindow_.add( editablePhotosView_ ); - iconWindow_.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_NEVER); imagesArea_.pack_start( iconWindow_, Gtk::PACK_EXPAND_WIDGET, 0 ); btNext_.add( right_ ); btNext_.set_relief( Gtk::RELIEF_NONE ); imagesArea_.pack_start( btNext_, Gtk::PACK_SHRINK, 2 ); - + hPane_.pack_start( vPane_, Gtk::PACK_EXPAND_WIDGET, 6); + vPane_.pack_start( imagesArea_, Gtk::PACK_SHRINK ); + hPane_.pack_start( filters_, Gtk::PACK_SHRINK, 6 ); + filters_.set_size_request( 200, -1 ); dockItem_ = gdl_dock_item_new_with_stock(dockItemName_.c_str(), dockItemTitle_.c_str(), Gtk::Stock::EDIT.id, dockItemBehaviour_); gtk_container_add(GTK_CONTAINER(dockItem_), - GTK_WIDGET(vPane_.gobj())); - vPane_.show_all_children(); + GTK_WIDGET(hPane_.gobj())); + hPane_.show_all_children(); } EditorRenderer::~EditorRenderer() throw() @@ -398,6 +428,38 @@ EditorRenderer::~EditorRenderer() throw() void EditorRenderer::init(Application & application) throw() { + //setup actions + Glib::RefPtr rotate( + Glib::RefPtr( + new RotateWidget( filters_, editor_ ) ) ); + filters_.add( rotate ); + Glib::RefPtr flip( + Glib::RefPtr( + new FlipWidget( filters_, editor_ ) ) ); + filters_.add( flip ); + Glib::RefPtr scale( + Glib::RefPtr( + new ScaleWidget( filters_, editor_ ) ) ); + filters_.add( scale ); + Glib::RefPtr brightness( + Glib::RefPtr( + new BrightnessWidget( filters_, editor_ ) ) ); + filters_.add( brightness ); + + Glib::RefPtr contrast( + Glib::RefPtr( + new ContrastWidget( filters_, editor_ ) ) ); + filters_.add( contrast ); + + Glib::RefPtr desaturate( + Glib::RefPtr( + new DesaturateWidget( filters_, editor_ ) ) ); + filters_.add( desaturate ); + + filters_.setup(); + filters_.signal_apply().connect( + sigc::mem_fun( *this, + &EditorRenderer::on_edit_action ) ); application_ = &application; editor_.init( application ); @@ -414,6 +476,19 @@ EditorRenderer::init(Application & application) throw() &EditorRenderer::on_photo_activated)); MainWindow & main_window = application.get_main_window(); + +#if 0 + const Glib::RefPtr & ui_manager + = main_window.get_ui_manager(); + Gtk::Toolbar * const tool_bar + = dynamic_cast( + ui_manager->get_widget("/ToolBarEdit")); + tool_bar->set_toolbar_style( Gtk::TOOLBAR_ICONS ); + + tool_bar->set_orientation( Gtk::ORIENTATION_VERTICAL ); + hPane_.pack_end( *tool_bar, Gtk::PACK_SHRINK, 0); +#endif + main_window.add_dock_object_center(GDL_DOCK_OBJECT(dockItem_)); signalInitEnd_ @@ -524,8 +599,8 @@ EditorRenderer::on_action_go_previous() throw() Gtk::TreeModel::Path path = photosModel_->get_path( currentItem_ ); editablePhotosView_.set_cursor( path, iconRenderer_, false ); - editablePhotosView_.item_activated( path ); editablePhotosView_.grab_focus(); + editablePhotosView_.item_activated( path ); } void @@ -550,8 +625,8 @@ EditorRenderer::on_action_go_next() throw() Gtk::TreeModel::Path path = photosModel_->get_path( currentItem_ ); editablePhotosView_.set_cursor( path, iconRenderer_, false ); - editablePhotosView_.item_activated( path ); editablePhotosView_.grab_focus(); + editablePhotosView_.item_activated( path ); } void @@ -773,7 +848,7 @@ EditorRenderer::on_switch_page(GtkNotebookPage * notebook_page, gtk_image_view_set_pixbuf( GTK_IMAGE_VIEW(imageView_), 0 , TRUE ); editor_.save(); - editor_.set_current_photo( EditablePhotoPtr() ); + editor_.set_current_photo( EditablePhotoPtr() ); ui_manager->remove_action_group(actionGroup_); ui_manager->remove_ui(uiID_); editor_.unregister_ui(); @@ -789,10 +864,9 @@ EditorRenderer::renderSelectedPhotos(const EditablePhotoList & photos) throw() for( EditablePhotoList::const_iterator photo = photos.begin(); photo != photos.end(); photo ++ ) { - ThumbbufMaker thumbbuf_maker( 128, 96 ); + ThumbbufMaker thumbbuf_maker( 48, 36 ); Gtk::TreeModel::Row row = *(photosModel_->append()); - row[ columns_.buffer_ ] = (*photo)->get_photo()->get_thumbnail_buffer(); - //->scale_simple( 128, 96, Gdk::INTERP_BILINEAR ); + row[ columns_.buffer_ ] = scale_buffer((*photo)->get_photo()->get_thumbnail_buffer()); row[ columns_.photo_ ] = (*photo); } signalPhotoSelected_.unblock(); @@ -804,11 +878,14 @@ EditorRenderer::renderSelectedPhotos(const EditablePhotoList & photos) throw() } void -EditorRenderer::render(const EditablePhotoPtr & photo) throw() +EditorRenderer::show(const EditablePhotoPtr & photo) throw() try { + if( !photo ) + return; PixbufPtr pixbuf = photo->get_buffer(); +#if 0 if( !pixbuf ) { Engine & engine = application_->get_engine(); @@ -821,10 +898,14 @@ try pixbuf = Gdk::Pixbuf::create_from_file(path); photo->set_buffer( pixbuf ); } +#endif + if( !pixbuf ) + return; gtk_image_view_set_pixbuf(GTK_IMAGE_VIEW(imageView_), pixbuf->gobj(), TRUE); + filters_.get_histogram_viewer().set( pixbuf ); } catch (const Glib::ConvertError & e) { @@ -848,9 +929,13 @@ EditorRenderer::refresh_image() throw() Gtk::TreeModel::Row row = *currentItem_; EditablePhotoPtr photo = row[ columns_.photo_ ]; ThumbbufMaker thumbbuf_maker( 128, 96 ); - row[ columns_.buffer_ ] = photo->get_photo()->get_thumbnail_buffer(); + row[ columns_.buffer_ ] = scale_buffer( photo->get_photo()->get_thumbnail_buffer() ); +#if 0 gtk_image_view_set_pixbuf(GTK_IMAGE_VIEW(imageView_), photo->get_buffer()->gobj(), TRUE); +#endif + std::cout<<"Showing..."<get_iter( path ); Gtk::TreeModel::Row row = *currentItem_; EditablePhotoPtr photo = row[ columns_.photo_ ]; +#if 0 + photo->get_edit_buffer()->get_refresh().connect( + sigc::bind( + sigc::mem_fun1( *this, &EditorRenderer::show ), photo )); +#endif editor_.set_current_photo( photo ); - render( photo ); + editor_.edit_action_performed().emit(); + //render( photo ); +} + +void +EditorRenderer::on_edit_action( const EditActionPtr &action ) throw() +{ + editor_.apply( action ); } } // namespace Solang diff --git a/src/renderer/editor-renderer.h b/src/renderer/editor-renderer.h index 67746d7..e557f15 100644 --- a/src/renderer/editor-renderer.h +++ b/src/renderer/editor-renderer.h @@ -27,6 +27,7 @@ #include #include "editor.h" +#include "editor-toolbar.h" #include "i-renderer.h" #include "thumbnail-view.h" #include "types.h" @@ -94,7 +95,7 @@ class EditorRenderer : renderSelectedPhotos(const EditablePhotoList & photos) throw(); virtual void - render(const EditablePhotoPtr & photo) throw(); + show(const EditablePhotoPtr & photo) throw(); void refresh_image() throw(); @@ -136,6 +137,9 @@ class EditorRenderer : on_switch_page(GtkNotebookPage * notebook_page, guint page_num) throw(); + void + on_edit_action( const EditActionPtr &) throw(); + ApplicationPtr application_; Glib::RefPtr iconFactory_; @@ -154,7 +158,11 @@ class EditorRenderer : GtkWidget * dockItem_; - Gtk::VPaned vPane_; + Gtk::VBox vPane_; + + Gtk::HBox hPane_; + + EditorToolbar filters_; GtkWidget * imageView_; -- 1.6.0.4