[gnome-photos/wip/rishi/orientation: 6/8] gegl: Add photos_gegl_buffer_apply_orientation



commit 195c4fa1e7c2d56534781af098c96b730ea3932f
Author: Debarshi Ray <debarshir gnome org>
Date:   Thu Nov 23 15:58:19 2017 +0100

    gegl: Add photos_gegl_buffer_apply_orientation
    
    This is part of a new set of APIs for GeglBuffer that don't require the
    creation of a graph. These will allow decoding and encoding image file
    formats to and from a GeglBuffer through asynchronous and cancellable
    methods with error handling. These will follow GIO idioms and be
    similar to the codec APIs for GdkPixbuf. There will be a compatibility
    layer to convert a GeglBuffer to and from GdkPixbuf for legacy reasons.
    
    These APIs will address the current lack of cancellation and error
    handling in gegl:load, and make it easier to port existing code away
    from GdkPixbuf.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=781736

 src/photos-gegl.c |  181 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/photos-gegl.h |    2 +
 2 files changed, 183 insertions(+), 0 deletions(-)
---
diff --git a/src/photos-gegl.c b/src/photos-gegl.c
index 85d4763..cd7ab72 100644
--- a/src/photos-gegl.c
+++ b/src/photos-gegl.c
@@ -16,6 +16,10 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+/* Based on code from:
+ *   + GIMP
+ */
+
 
 #include "config.h"
 
@@ -67,6 +71,183 @@ static const gchar *REQUIRED_GEGL_OPS[] =
 
 
 GeglBuffer *
+photos_gegl_buffer_apply_orientation (GeglBuffer *buffer_original, GQuark orientation)
+{
+  const Babl *format;
+  g_autoptr (GeglBuffer) buffer_oriented = NULL;
+  GeglBuffer *ret_val = NULL;
+  GeglRectangle bbox_oriented;
+  GeglRectangle bbox_original;
+  gint bpp;
+
+  g_message ("%s", g_quark_to_string (orientation));
+
+  g_return_val_if_fail (orientation == PHOTOS_ORIENTATION_BOTTOM
+                        || orientation == PHOTOS_ORIENTATION_LEFT
+                        || orientation == PHOTOS_ORIENTATION_RIGHT
+                        || orientation == PHOTOS_ORIENTATION_TOP,
+                        NULL);
+
+  if (orientation == PHOTOS_ORIENTATION_TOP)
+    {
+      ret_val = g_object_ref (buffer_original);
+      goto out;
+    }
+
+  bbox_original = *gegl_buffer_get_extent (buffer_original);
+
+  if (orientation == PHOTOS_ORIENTATION_BOTTOM)
+    {
+      /* angle = 180 degrees */
+      bbox_oriented.height = bbox_original.height;
+      bbox_oriented.width = bbox_original.width;
+      bbox_oriented.x = -(bbox_original.x + bbox_original.width);
+      bbox_oriented.y = -(bbox_original.y + bbox_original.height);
+    }
+  else if (orientation == PHOTOS_ORIENTATION_LEFT)
+    {
+      /* angle = -270 or 90 degrees counterclockwise */
+      bbox_oriented.height = bbox_original.width;
+      bbox_oriented.width = bbox_original.height;
+      bbox_oriented.x = bbox_original.y;
+      bbox_oriented.y = -(bbox_original.x + bbox_original.width);
+    }
+  else if (orientation == PHOTOS_ORIENTATION_RIGHT)
+    {
+      /* angle = -90 or 270 degrees counterclockwise */
+      bbox_oriented.height = bbox_original.width;
+      bbox_oriented.width = bbox_original.height;
+      bbox_oriented.x = -(bbox_original.y + bbox_original.height);
+      bbox_oriented.y = bbox_original.x;
+    }
+  else
+    {
+      g_return_val_if_reached (NULL);
+    }
+
+  format = gegl_buffer_get_format (buffer_original);
+  bpp = babl_format_get_bytes_per_pixel (format);
+  buffer_oriented = gegl_buffer_new (&bbox_oriented, format);
+
+  if (orientation == PHOTOS_ORIENTATION_BOTTOM)
+    {
+      GeglRectangle bbox_destination;
+      GeglRectangle bbox_source;
+      g_autofree guchar *buf = NULL;
+      gint i;
+
+      /* angle = 180 degrees */
+
+      g_return_val_if_fail (bbox_oriented.height == bbox_original.height, NULL);
+      g_return_val_if_fail (bbox_oriented.width == bbox_original.width, NULL);
+
+      gegl_rectangle_set (&bbox_destination, bbox_oriented.x, bbox_oriented.y, (guint) bbox_oriented.width, 
1);
+
+      bbox_source.x = bbox_original.x;
+      bbox_source.y = bbox_original.y + bbox_original.height - 1;
+      bbox_source.height = 1;
+      bbox_source.width = bbox_original.width;
+
+      buf = g_malloc0_n (bbox_oriented.width, bpp);
+
+      for (i = 0; i < bbox_original.height; i++)
+        {
+          gint j;
+
+          gegl_buffer_get (buffer_original, &bbox_source, 1.0, format, buf, GEGL_AUTO_ROWSTRIDE, 
GEGL_ABYSS_NONE);
+
+          for (j = 0; j < bbox_original.width / 2; j++)
+            {
+              gint k;
+              guchar *pixel_left = buf + j * bpp;
+              guchar *pixel_right = buf + (bbox_original.width - 1 - j) * bpp;
+
+              for (k = 0; k < bpp; k++)
+                {
+                  guchar tmp = pixel_left[k];
+
+                  pixel_left[k] = pixel_right[k];
+                  pixel_right[k] = tmp;
+                }
+            }
+
+          gegl_buffer_set (buffer_oriented, &bbox_destination, 0, format, buf, GEGL_AUTO_ROWSTRIDE);
+
+          bbox_destination.y++;
+          bbox_source.y--;
+        }
+    }
+  else if (orientation == PHOTOS_ORIENTATION_LEFT)
+    {
+      GeglRectangle bbox_destination;
+      GeglRectangle bbox_source;
+      g_autofree guchar *buf = NULL;
+      gint i;
+
+      /* angle = -270 or 90 degrees counterclockwise */
+
+      g_return_val_if_fail (bbox_oriented.height == bbox_original.width, NULL);
+      g_return_val_if_fail (bbox_oriented.width == bbox_original.height, NULL);
+
+      gegl_rectangle_set (&bbox_destination, bbox_oriented.x, bbox_oriented.y, (guint) bbox_oriented.width, 
1);
+
+      bbox_source.x = bbox_original.x + bbox_original.width - 1;
+      bbox_source.y = bbox_original.y;
+      bbox_source.height = bbox_original.height;
+      bbox_source.width = 1;
+
+      buf = g_malloc0_n (bbox_oriented.width, bpp);
+
+      for (i = 0; i < bbox_original.width; i++)
+        {
+          gegl_buffer_get (buffer_original, &bbox_source, 1.0, format, buf, GEGL_AUTO_ROWSTRIDE, 
GEGL_ABYSS_NONE);
+          gegl_buffer_set (buffer_oriented, &bbox_destination, 0, format, buf, GEGL_AUTO_ROWSTRIDE);
+          bbox_destination.y++;
+          bbox_source.x--;
+        }
+    }
+  else if (orientation == PHOTOS_ORIENTATION_RIGHT)
+    {
+      GeglRectangle bbox_destination;
+      GeglRectangle bbox_source;
+      g_autofree guchar *buf = NULL;
+      gint i;
+
+      /* angle = -90 or 270 degrees counterclockwise */
+
+      g_return_val_if_fail (bbox_oriented.height == bbox_original.width, NULL);
+      g_return_val_if_fail (bbox_oriented.width == bbox_original.height, NULL);
+
+      gegl_rectangle_set (&bbox_destination, bbox_oriented.x, bbox_oriented.y, 1, (guint) 
bbox_oriented.height);
+
+      bbox_source.x = bbox_original.x;
+      bbox_source.y = bbox_original.y + bbox_original.height - 1;
+      bbox_source.height = 1;
+      bbox_source.width = bbox_original.width;
+
+      buf = g_malloc0_n (bbox_oriented.height, bpp);
+
+      for (i = 0; i < bbox_original.height; i++)
+        {
+          gegl_buffer_get (buffer_original, &bbox_source, 1.0, format, buf, GEGL_AUTO_ROWSTRIDE, 
GEGL_ABYSS_NONE);
+          gegl_buffer_set (buffer_oriented, &bbox_destination, 0, format, buf, GEGL_AUTO_ROWSTRIDE);
+          bbox_destination.x++;
+          bbox_source.y--;
+        }
+    }
+  else
+    {
+      g_return_val_if_reached (NULL);
+    }
+
+  ret_val = g_object_ref (buffer_oriented);
+
+ out:
+  return ret_val;
+}
+
+
+GeglBuffer *
 photos_gegl_buffer_new_from_pixbuf (GdkPixbuf *pixbuf)
 {
   const Babl *format;
diff --git a/src/photos-gegl.h b/src/photos-gegl.h
index b7e39e7..516c82f 100644
--- a/src/photos-gegl.h
+++ b/src/photos-gegl.h
@@ -27,6 +27,8 @@
 
 G_BEGIN_DECLS
 
+GeglBuffer      *photos_gegl_buffer_apply_orientation     (GeglBuffer *buffer_original, GQuark orientation);
+
 GeglBuffer      *photos_gegl_buffer_new_from_pixbuf       (GdkPixbuf *pixbuf);
 
 void             photos_gegl_buffer_zoom_async            (GeglBuffer *buffer,


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