[gtk/wip/otte/color-profiles: 17/40] memorytexture: Add gdk_memory_texture_convert()




commit 61f1dde5fe1b9f4ba496d03a50f8aeed02e9f1de
Author: Benjamin Otte <otte redhat com>
Date:   Sat Sep 25 21:15:18 2021 +0200

    memorytexture: Add gdk_memory_texture_convert()
    
    Converts a memory texture to a new one with a specific format and color
    profile. You can even pass a rectangle to restrict the result to a given
    region.
    
    The code is well optimized, so it avoids copies if things match and will
    in fact return the texture itself if the same colorspace and format and
    no/the full rectangle are passed, so it can be used without fear of
    performance implications.
    
    In fact, the following code should be used - without any additional
    checks - to turn any texture into a desired color profile and format
    (say for saving with gdk-pixbuf):
    
    memtex = gdk_texture_download (texture);
    memtex = gdk_memory_texture_convert (memory_texture,
                                         GDK_MEMORY_R8G8B8A8,
                                         gdk_color_profile_get_srgb(),
                                         NULL);
    pixbuf = gdk_pixbuf_new_from_data (gdk_memory_texture_get_data (memtex),
                                       GDK_COLOR_SPACE_RGB,
                                       TRUE,
                                       8
                                       gdk_texture_get_width (memtex),
                                       gdk_texture_get_height (memtex),
                                       gdk_memory_texture_get_stride (memtex),
                                       g_object_unref_wrapper,
                                       memtex);

 gdk/gdkmemorytexture.c        | 76 +++++++++++++++++++++++++++++++++++++++++++
 gdk/gdkmemorytextureprivate.h | 12 +++++--
 2 files changed, 85 insertions(+), 3 deletions(-)
---
diff --git a/gdk/gdkmemorytexture.c b/gdk/gdkmemorytexture.c
index 3f64b423f3..2da8380aa2 100644
--- a/gdk/gdkmemorytexture.c
+++ b/gdk/gdkmemorytexture.c
@@ -235,12 +235,88 @@ gdk_memory_texture_new_with_color_profile (int              width,
   return GDK_TEXTURE (self);
 }
 
+GdkMemoryTexture *
+gdk_memory_texture_convert (GdkMemoryTexture   *source,
+                            GdkMemoryFormat     to_format,
+                            GdkColorProfile    *to_profile,
+                            const GdkRectangle *rect_or_null)
+{
+  GdkTexture *texture = GDK_TEXTURE (source);
+  GdkTexture *result;
+  GBytes *to_bytes;
+  int width, height;
+  gsize offset, stride;
+
+  width = texture->width;
+  height = texture->height;
+  if (rect_or_null)
+    {
+      g_assert (rect_or_null->x + rect_or_null->width <= width);
+      g_assert (rect_or_null->y + rect_or_null->height <= height);
+
+      offset = rect_or_null->y * source->stride +
+               rect_or_null->x * gdk_memory_format_bytes_per_pixel (source->format);
+      width = rect_or_null->width;
+      height = rect_or_null->height;
+    }
+  else
+    offset = 0;
+
+  if (to_format == source->format &&
+      gdk_color_profile_equal (texture->color_profile, to_profile))
+    {
+      if (offset == 0 && width == texture->width && height == texture->height)
+        return source;
+
+      to_bytes = g_bytes_new_from_bytes (source->bytes,
+                                         offset,
+                                         source->stride * height);
+      stride = source->stride;
+    }
+  else
+    {
+      guchar *data;
+
+      stride = gdk_memory_format_bytes_per_pixel (to_format) * width;
+      data = g_malloc_n (stride, height);
+      gdk_memory_convert (data,
+                          stride,
+                          to_format,
+                          to_profile,
+                          (guchar *) g_bytes_get_data (source->bytes, NULL) + offset,
+                          source->stride,
+                          source->format,
+                          texture->color_profile,
+                          width,
+                          height);
+      to_bytes = g_bytes_new_take (data, stride * height);
+    }
+
+  result = gdk_memory_texture_new_with_color_profile (width,
+                                                      height,
+                                                      to_format,
+                                                      to_profile,
+                                                      to_bytes,
+                                                      stride);
+
+  g_bytes_unref (to_bytes);
+  g_object_unref (source);
+
+  return GDK_MEMORY_TEXTURE (result);
+}
+
 GdkMemoryFormat 
 gdk_memory_texture_get_format (GdkMemoryTexture *self)
 {
   return self->format;
 }
 
+GBytes *
+gdk_memory_texture_get_bytes (GdkMemoryTexture *self)
+{
+  return self->bytes;
+}
+
 const guchar *
 gdk_memory_texture_get_data (GdkMemoryTexture *self)
 {
diff --git a/gdk/gdkmemorytextureprivate.h b/gdk/gdkmemorytextureprivate.h
index f61cccb9ef..8966decb24 100644
--- a/gdk/gdkmemorytextureprivate.h
+++ b/gdk/gdkmemorytextureprivate.h
@@ -29,9 +29,15 @@ G_BEGIN_DECLS
 #define GDK_MEMORY_GDK_PIXBUF_OPAQUE GDK_MEMORY_R8G8B8
 #define GDK_MEMORY_GDK_PIXBUF_ALPHA GDK_MEMORY_R8G8B8A8
 
-GdkMemoryFormat         gdk_memory_texture_get_format       (GdkMemoryTexture  *self);
-const guchar *          gdk_memory_texture_get_data         (GdkMemoryTexture  *self);
-gsize                   gdk_memory_texture_get_stride       (GdkMemoryTexture  *self);
+GdkMemoryTexture *      gdk_memory_texture_convert              (GdkMemoryTexture       *source,
+                                                                 GdkMemoryFormat         to_format,
+                                                                 GdkColorProfile        *to_profile,
+                                                                 const GdkRectangle     *rect_or_null);
+
+GdkMemoryFormat         gdk_memory_texture_get_format           (GdkMemoryTexture       *self);
+GBytes *                gdk_memory_texture_get_bytes            (GdkMemoryTexture       *self);
+const guchar *          gdk_memory_texture_get_data             (GdkMemoryTexture       *self);
+gsize                   gdk_memory_texture_get_stride           (GdkMemoryTexture       *self);
 
 
 G_END_DECLS


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