[gnome-photos/wip/rishi/orientation: 6/8] gegl: Add photos_gegl_buffer_apply_orientation
- From: Debarshi Ray <debarshir src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-photos/wip/rishi/orientation: 6/8] gegl: Add photos_gegl_buffer_apply_orientation
- Date: Thu, 23 Nov 2017 19:34:21 +0000 (UTC)
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]