[niepce] Add rotation commands to ncr::Image.



commit 5fd057c1b7fb376e98d85dc5122c7c5f79638378
Author: Hubert Figuiere <hub figuiere net>
Date:   Thu May 21 18:00:20 2009 -0400

    Add rotation commands to ncr::Image.
---
 ChangeLog         |    4 ++
 src/ncr/image.cpp |   86 +++++++++++++++++++++++++++++++++++++++++------------
 src/ncr/image.hpp |   15 +++++++++
 3 files changed, 86 insertions(+), 19 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 1c9ae14..9372b9f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2009-06-04  Hubert Figuiere  <hub figuiere net>
+
+	* Add rotation commands to ncr::Image.
+
 2009-05-26  Hubert Figuiere  <hub figuiere net>
 
 	* README: 
diff --git a/src/ncr/image.cpp b/src/ncr/image.cpp
index 03bb956..c8c9cf8 100644
--- a/src/ncr/image.cpp
+++ b/src/ncr/image.cpp
@@ -62,14 +62,21 @@ const Babl * format_for_cairo_argb32()
 
 struct Image::Private {
     Private()
-        : m_width(0),
-          m_height(0)
+        : m_width(0)
+        , m_height(0)
+        , m_orientation(0)
+        , m_flip(false)
+        , m_tilt(0.0)
         {
         }
 
     int m_width, m_height; /**< the native dimension, with orientation */
+    int m_orientation;     /**< EXIF orientation in degrees */
+    bool m_flip;           /**< EXIF flip */
+    double m_tilt;         /**< User rotation */
     Glib::RefPtr<Gegl::Node> m_node;
     Glib::RefPtr<Gegl::Node> m_rgb;    /**< RGB pixmap */
+    Glib::RefPtr<Gegl::Node> m_rotate_n;
     Glib::RefPtr<Gegl::Node> m_scale;
     Glib::RefPtr<Gegl::Node> m_output;
 };
@@ -139,51 +146,49 @@ void Image::reload(const std::string & p, bool is_raw,
     Glib::RefPtr<Gegl::Node> current;
 
     DBG_OUT("rotation is %d", orientation);
-    int degrees = 0;
     bool vertical = false;
-    bool flip = false;
     switch(orientation) {
     case 0:
     case 1:
         break;
     case 2:
-        flip = true;
+        priv->m_flip = true;
         break;
     case 4:
-        flip = true;
+        priv->m_flip = true;
         // fall through
     case 3:
-        degrees = 180;
+        priv->m_orientation = 180;
         break;
     case 5:
-        flip = true;
+        priv->m_flip = true;
         // fall through
     case 6:
-        degrees = 270;
+        priv->m_orientation = 270;
         vertical = true;
         break;
     case 7:
-        flip = true;
+        priv->m_flip = true;
         // fall through
     case 8:
-        degrees = 90;
+        priv->m_orientation = 90;
         vertical = true;
         break;
     }
     // @todo ideally we would have a plain GEGL op for that.
-    Glib::RefPtr<Gegl::Node> rotate;
-    if(flip) {
+    if(priv->m_flip) {
         // @todo find a test case.
-        rotate =  priv->m_node->new_child("operation", "gegl:reflect");
-        rotate->set("x", -1.0);
-        current = priv->m_rgb->link(rotate);
+        priv->m_rotate_n =  priv->m_node->new_child("operation", 
+                                                    "gegl:reflect");
+        priv->m_rotate_n->set("x", -1.0);
+        current = priv->m_rgb->link(priv->m_rotate_n);
     }
     else {
         current = priv->m_rgb;
     }
-    rotate = priv->m_node->new_child("operation", "gegl:rotate");
-    rotate->set("degrees", degrees);
-    current = current->link(rotate);
+    priv->m_rotate_n = priv->m_node->new_child("operation", "gegl:rotate");
+    priv->m_rotate_n->set("degrees", priv->m_orientation + priv->m_tilt);
+    current = current->link(priv->m_rotate_n);
 
     priv->m_scale = priv->m_node->new_child("operation", "gegl:scale");
     current->link(priv->m_scale);
@@ -217,6 +222,49 @@ void Image::set_output_scale(double scale)
 }
 
 
+
+void Image::set_tilt(double angle)
+{
+    priv->m_tilt = angle;
+    priv->m_rotate_n->set("degrees", priv->m_orientation + priv->m_tilt);
+
+    signal_update();    
+}
+
+
+void Image::rotate_left()
+{
+    rotate_by(-90);
+}
+
+void Image::rotate_right()
+{
+    rotate_by(90);
+}
+
+void Image::rotate_half()
+{
+    rotate_by(180);
+}
+
+
+void Image::rotate_by(int degree)
+{
+    priv->m_orientation += degree;
+    if(priv->m_orientation < 0) {
+        // negative values aren't good
+        priv->m_orientation += 360;
+    }
+    else {
+        // within 0..359 degrees anyway
+        priv->m_orientation %= 360;
+    }
+    priv->m_rotate_n->set("degrees", priv->m_orientation + priv->m_tilt);
+    signal_update();
+}
+
+
+
 Cairo::RefPtr<Cairo::Surface> Image::cairo_surface_for_display()
 {
     priv->m_output->process();
diff --git a/src/ncr/image.hpp b/src/ncr/image.hpp
index 89ce5cc..b234cf5 100644
--- a/src/ncr/image.hpp
+++ b/src/ncr/image.hpp
@@ -54,7 +54,16 @@ public:
     /** set the output scale */
     void set_output_scale(double scale);
 
+    /** tile the image in degrees. */
     void set_tilt(double angle);
+
+    /** rotate the image left */
+    void rotate_left();
+    /** rotate the image right */
+    void rotate_right();
+    /** rotate 180 degres */
+    void rotate_half();
+
     void set_color_temp(int temp);
     void set_exposure(double exposure);
     void set_brightness(int brightness);
@@ -66,6 +75,12 @@ public:
         image is changed. */
     sigc::signal<void> signal_update;
 private:
+
+    /** rotate by x degrees (orientation) 
+     *  ensure the end results is within 0..359.
+     */
+    void rotate_by(int degree);
+
     class Private;
     Private *priv;
 };



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]