[gtk+/gtk-2-24] quartz: honor more source image properties in _gdk_quartz_image_copy_to_image()



commit 9754c51349d14fcb1438fac3ddc7565b4d77b53c
Author: Michael Natterer <mitch lanedo com>
Date:   Fri May 17 15:24:15 2013 +0200

    quartz: honor more source image properties in _gdk_quartz_image_copy_to_image()
    
    Particularly look at the source image's byte order when making a
    screenshot of the "root window" (which is the window stack). Make
    the code more generic so it can handle all sorts of pixel formats.

 gdk/quartz/gdkimage-quartz.c |   75 +++++++++++++++++++++++++++++++++++-------
 1 files changed, 63 insertions(+), 12 deletions(-)
---
diff --git a/gdk/quartz/gdkimage-quartz.c b/gdk/quartz/gdkimage-quartz.c
index 1d4f8d7..493efba 100644
--- a/gdk/quartz/gdkimage-quartz.c
+++ b/gdk/quartz/gdkimage-quartz.c
@@ -134,6 +134,14 @@ _gdk_quartz_image_copy_to_image (GdkDrawable *drawable,
       guchar *data;
       int x, y;
       NSSize size;
+      NSBitmapFormat format;
+      gboolean has_alpha;
+      gint bpp;
+      gint r_byte = 0;
+      gint g_byte = 1;
+      gint b_byte = 2;
+      gint a_byte = 3;
+      gboolean le_image_data = FALSE;
 
       if (GDK_WINDOW_IMPL_QUARTZ (drawable) == GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (_gdk_root)->impl))
         {
@@ -143,6 +151,23 @@ _gdk_quartz_image_copy_to_image (GdkDrawable *drawable,
                                                                kCGWindowListOptionOnScreenOnly,
                                                                kCGNullWindowID,
                                                                kCGWindowImageDefault);
+
+          /* HACK: the NSBitmapImageRep does not copy and convert
+           * CGImageRef's data so it matches what NSBitmapImageRep can
+           * express in its API (which is RGBA and ARGB, premultiplied
+           * and unpremultiplied), it only references the CGImageRef.
+           * Therefore we need to do the host byte swapping ourselves.
+           */
+          if (CGImageGetBitmapInfo (root_image_ref) & kCGBitmapByteOrder32Little)
+            {
+              r_byte = 3;
+              g_byte = 2;
+              b_byte = 1;
+              a_byte = 0;
+
+              le_image_data = TRUE;
+            }
+
           rep = [[NSBitmapImageRep alloc] initWithCGImage: root_image_ref];
           CGImageRelease (root_image_ref);
         }
@@ -158,9 +183,24 @@ _gdk_quartz_image_copy_to_image (GdkDrawable *drawable,
           rep = [[NSBitmapImageRep alloc] initWithFocusedViewRect: rect];
           [view unlockFocus];
         }
-         
+
       data = [rep bitmapData];
       size = [rep size];
+      format = [rep bitmapFormat];
+      has_alpha = [rep hasAlpha];
+      bpp = [rep bitsPerPixel] / 8;
+
+      /* MORE HACK: AlphaFirst seems set for le_image_data, which is
+       * technically correct, but really apple, are you kidding, it's
+       * in fact ABGR, not ARGB as promised in NSBitmapImageRep's API.
+       */
+      if (!le_image_data && (format & NSAlphaFirstBitmapFormat))
+        {
+          r_byte = 1;
+          g_byte = 2;
+          b_byte = 3;
+          a_byte = 0;
+        }
 
       for (y = 0; y < size.height; y++)
         {
@@ -168,27 +208,38 @@ _gdk_quartz_image_copy_to_image (GdkDrawable *drawable,
 
           for (x = 0; x < size.width; x++)
             {
+              guchar r = src[r_byte];
+              guchar g = src[g_byte];
+              guchar b = src[b_byte];
               gint32 pixel;
 
-              if ([rep hasAlpha])
+              if (has_alpha)
                 {
-                  if (image->byte_order == GDK_LSB_FIRST)
-                    pixel = src[3] | src[2] << 8 | src[1] << 16 | src[0] << 24;
+                  guchar alpha = src[a_byte];
+
+                  /* unpremultiply if alpha > 0 */
+                  if (! (format & NSAlphaNonpremultipliedBitmapFormat) && alpha)
+                    {
+                      r = r * 255 / alpha;
+                      g = g * 255 / alpha;
+                      b = b * 255 / alpha;
+                    }
+
+                  if (image->byte_order == GDK_MSB_FIRST)
+                    pixel = alpha | b << 8 | g << 16 | r << 24;
                   else
-                    pixel = src[3] << 24 | src[2] << 16 | src[1] << 8 | src[0];
-
-                  src += [rep bitsPerPixel] / 8;
+                    pixel = alpha << 24 | b << 16 | g << 8 | r;
                 }
               else
                 {
-                  if (image->byte_order == GDK_LSB_FIRST)
-                    pixel = src[3] | src[2] << 8 |src[1] << 16;
+                  if (image->byte_order == GDK_MSB_FIRST)
+                    pixel = b | g << 8 | r << 16;
                   else
-                    pixel = src[3] << 16 | src[2] << 8 |src[1];
-
-                  src += [rep bitsPerPixel] / 8;
+                    pixel = b << 16 | g << 8 | r;
                 }
 
+              src += bpp;
+
               gdk_image_put_pixel (image, dest_x + x, dest_y + y, pixel);
             }
         }


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