[gnome-photos] base-item: Add photos_base_item_create_preview
- From: Debarshi Ray <debarshir src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-photos] base-item: Add photos_base_item_create_preview
- Date: Fri, 27 Nov 2015 17:55:43 +0000 (UTC)
commit f2412e09bb18a8fe5c47d7cc5e69a961bf21b631
Author: Debarshi Ray <debarshir gnome org>
Date: Mon Nov 23 20:57:51 2015 +0100
base-item: Add photos_base_item_create_preview
The implementation is synchronous because we are not doing any I/O and
we expect it to become really fast when mipmapping is enabled. At the
moment, without mipmaps, it isn't as fast as it should be, but it isn't
absolutely horrible either.
src/photos-base-item.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++
src/photos-base-item.h | 7 +++
2 files changed, 118 insertions(+), 0 deletions(-)
---
diff --git a/src/photos-base-item.c b/src/photos-base-item.c
index 7ee60ad..90b4333 100644
--- a/src/photos-base-item.c
+++ b/src/photos-base-item.c
@@ -30,6 +30,7 @@
#include <string.h>
#include <gdk/gdk.h>
+#include <gegl-plugin.h>
#include <gio/gio.h>
#include <glib.h>
#include <glib/gi18n.h>
@@ -1380,6 +1381,116 @@ photos_base_item_can_trash (PhotosBaseItem *self)
}
+cairo_surface_t *
+photos_base_item_create_preview (PhotosBaseItem *self,
+ gint size,
+ gint scale,
+ const gchar *operation,
+ const gchar *first_property_name,
+ ...)
+{
+ PhotosBaseItemPrivate *priv = self->priv;
+ GeglBuffer *buffer_orig = NULL;
+ GeglBuffer *buffer = NULL;
+ GeglNode *buffer_source;
+ GeglNode *crop;
+ GeglNode *graph = NULL;
+ GeglNode *operation_node;
+ GeglOperation *op;
+ GeglProcessor *processor = NULL;
+ GeglRectangle bbox;
+ GeglRectangle roi;
+ cairo_surface_t *surface = NULL;
+ static const cairo_user_data_key_t key;
+ const Babl *format;
+ const gchar *name;
+ gdouble x;
+ gdouble y;
+ gdouble zoom;
+ gint min_dimension;
+ gint size_scaled;
+ gint stride;
+ gint64 end;
+ gint64 start;
+ guchar *buf = NULL;
+ va_list ap;
+
+ g_return_val_if_fail (operation != NULL && operation[0] != '\0', NULL);
+ g_return_val_if_fail (priv->buffer_source != NULL, NULL);
+ g_return_val_if_fail (priv->edit_graph != NULL, NULL);
+ g_return_val_if_fail (priv->load_graph != NULL, NULL);
+
+ op = gegl_node_get_gegl_operation (priv->buffer_source);
+ g_return_val_if_fail (op != NULL, NULL);
+
+ name = gegl_operation_get_name (op);
+ g_return_val_if_fail (g_strcmp0 (name, "gegl:buffer-source") == 0, NULL);
+
+ gegl_node_get (priv->buffer_source, "buffer", &buffer_orig, NULL);
+ buffer = gegl_buffer_dup (buffer_orig);
+
+ bbox = *gegl_buffer_get_extent (buffer);
+ min_dimension = bbox.height < bbox.width ? bbox.height : bbox.width;
+ x = (gdouble) (bbox.width - min_dimension) / 2.0;
+ y = (gdouble) (bbox.height - min_dimension) / 2.0;
+ size_scaled = size * scale;
+ zoom = (gdouble) size_scaled / (gdouble) min_dimension;
+
+ graph = gegl_node_new ();
+ buffer_source = gegl_node_new_child (graph, "operation", "gegl:buffer-source", "buffer", buffer, NULL);
+ crop = gegl_node_new_child (graph,
+ "operation", "gegl:crop",
+ "height", (gdouble) min_dimension,
+ "width", (gdouble) min_dimension,
+ "x", x,
+ "y", y,
+ NULL);
+
+ operation_node = gegl_node_new_child (graph, "operation", operation, NULL);
+
+ va_start (ap, first_property_name);
+ gegl_node_set_valist (operation_node, first_property_name, ap);
+ va_end (ap);
+
+ gegl_node_link_many (buffer_source, crop, operation_node, NULL);
+ processor = gegl_node_new_processor (operation_node, NULL);
+
+ start = g_get_monotonic_time ();
+
+ while (gegl_processor_work (processor, NULL));
+
+ end = g_get_monotonic_time ();
+ photos_debug (PHOTOS_DEBUG_GEGL, "Create Preview: Process: %" G_GINT64_FORMAT, end - start);
+
+ roi.height = size_scaled;
+ roi.width = size_scaled;
+ roi.x = (gint) (x * zoom + 0.5);
+ roi.y = (gint) (y * zoom + 0.5);
+
+ stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, roi.width);
+ buf = g_malloc0 (stride * roi.height);
+ format = babl_format ("cairo-ARGB32");
+
+ start = g_get_monotonic_time ();
+
+ gegl_node_blit (operation_node, zoom, &roi, format, buf, GEGL_AUTO_ROWSTRIDE, GEGL_BLIT_DEFAULT);
+
+ end = g_get_monotonic_time ();
+ photos_debug (PHOTOS_DEBUG_GEGL, "Create Preview: Node Blit: %" G_GINT64_FORMAT, end - start);
+
+ surface = cairo_image_surface_create_for_data (buf, CAIRO_FORMAT_ARGB32, roi.width, roi.height, stride);
+ cairo_surface_set_device_scale (surface, (gdouble) scale, (gdouble) scale);
+ cairo_surface_set_user_data (surface, &key, buf, (cairo_destroy_func_t) g_free);
+
+ g_object_unref (buffer);
+ g_object_unref (buffer_orig);
+ g_object_unref (graph);
+ g_object_unref (processor);
+
+ return surface;
+}
+
+
void
photos_base_item_destroy (PhotosBaseItem *self)
{
diff --git a/src/photos-base-item.h b/src/photos-base-item.h
index 884e925..7cf2ba8 100644
--- a/src/photos-base-item.h
+++ b/src/photos-base-item.h
@@ -91,6 +91,13 @@ GType photos_base_item_get_type (void) G_GNUC_CONST
gboolean photos_base_item_can_trash (PhotosBaseItem *self);
+cairo_surface_t *photos_base_item_create_preview (PhotosBaseItem *self,
+ gint size,
+ gint scale,
+ const gchar *operation,
+ const gchar *first_property_name,
+ ...) G_GNUC_NULL_TERMINATED
G_GNUC_WARN_UNUSED_RESULT;
+
void photos_base_item_destroy (PhotosBaseItem *self);
gchar *photos_base_item_download (PhotosBaseItem *self,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]