Author: mdk
Date: 2008-02-18 05:58:03 -0500 (Mon, 18 Feb 2008)
New Revision: 96044
Modified:
trunk/moon/src/ChangeLog
trunk/moon/src/media.cpp
trunk/moon/src/media.h
Log:
2008-02-18 Michael Dominic K. <[EMAIL PROTECTED]>
* src/media.cpp:
* src/media.h: Load images slightly faster by skipping one pixbuf blit
and
doing the expansion + conversion in one step.
Also fixing an ugly memory leak where all RGBA images loaded were leaked
(two times in memory).
Modified: trunk/moon/src/ChangeLog
===================================================================
--- trunk/moon/src/ChangeLog 2008-02-18 10:52:37 UTC (rev 96043)
+++ trunk/moon/src/ChangeLog 2008-02-18 10:58:03 UTC (rev 96044)
@@ -1,3 +1,12 @@
+2008-02-18 Michael Dominic K. <[EMAIL PROTECTED]>
+
+ * src/media.cpp:
+ * src/media.h: Load images slightly faster by skipping one pixbuf blit
and
+ doing the expansion + conversion in one step.
+
+ Also fixing an ugly memory leak where all RGBA images loaded were leaked
+ (two times in memory).
+
2008-02-15 Michael Dominic K. <[EMAIL PROTECTED]>
* src/clock.cpp: Before processing dirty enter/leave gdk threads. We're
Modified: trunk/moon/src/media.cpp
===================================================================
--- trunk/moon/src/media.cpp 2008-02-18 10:52:37 UTC (rev 96043)
+++ trunk/moon/src/media.cpp 2008-02-18 10:58:03 UTC (rev 96044)
@@ -4,6 +4,7 @@
* Authors:
* Jeffrey Stedfast <[EMAIL PROTECTED]>
* Jb Evain <[EMAIL PROTECTED]>
+ * Michael Dominic K. <[EMAIL PROTECTED]>
*
* Copyright 2007 Novell, Inc. (http://www.novell.com)
*
@@ -1611,6 +1612,8 @@
cairo_surface_destroy (surface->cairo);
if (surface->backing_pixbuf)
g_object_unref (surface->backing_pixbuf);
+ if (surface->backing_data)
+ g_free (surface->backing_data);
g_free (surface);
}
@@ -1735,10 +1738,83 @@
g = ((color & 0x0000ff00) >> 8); \
b = (color & 0x000000ff); \
} while(0)
+#define get_pixel_bgr(color, b, g, r) do { \
+ r = ((color & 0x00ff0000) >> 16); \
+ g = ((color & 0x0000ff00) >> 8); \
+ b = (color & 0x000000ff); \
+ } while(0)
#include "alpha-premul-table.inc"
+//
+// Expands RGB to ARGB allocating new buffer for it.
+//
+static guchar*
+expand_rgb_to_argb (GdkPixbuf *pixbuf, int *stride)
+{
+ guchar *pb_pixels = gdk_pixbuf_get_pixels (pixbuf);
+ guchar *p;
+ int w = gdk_pixbuf_get_width (pixbuf);
+ int h = gdk_pixbuf_get_height (pixbuf);
+ *stride = w * 4;
+ guchar *data = (guchar *) g_malloc (*stride * h);
+ guchar *out;
+ for (int y = 0; y < h; y ++) {
+ p = pb_pixels + y * gdk_pixbuf_get_rowstride (pixbuf);
+ out = data + y * (*stride);
+ for (int x = 0; x < w; x ++) {
+ guint32 color = *(guint32*)p;
+ guchar r, g, b;
+
+ get_pixel_bgr (color, b, g, r);
+ set_pixel_bgra (out, 0, r, g, b, 255);
+
+ p += 3;
+ out += 4;
+ }
+ }
+
+ return data;
+}
+
+//
+// Converts RGBA unmultiplied alpha to ARGB pre-multiplied alpha.
+//
+static void
+unmultiply_rgba_in_place (GdkPixbuf *pixbuf)
+{
+ guchar *pb_pixels = gdk_pixbuf_get_pixels (pixbuf);
+ guchar *p;
+ int w = gdk_pixbuf_get_width (pixbuf);
+ int h = gdk_pixbuf_get_height (pixbuf);
+
+ for (int y = 0; y < h; y ++) {
+ p = pb_pixels + y * gdk_pixbuf_get_rowstride (pixbuf);
+ for (int x = 0; x < w; x ++) {
+ guint32 color = *(guint32*)p;
+ guchar r, g, b, a;
+
+ get_pixel_bgra (color, b, g, r, a);
+
+ /* pre-multipled alpha */
+ if (a == 0) {
+ r = g = b = 0;
+ }
+ else if (a < 255) {
+ r = pre_multiplied_table [r][a];
+ g = pre_multiplied_table [g][a];
+ b = pre_multiplied_table [b][a];
+ }
+
+ /* store it back, swapping red and blue */
+ set_pixel_bgra (p, 0, r, g, b, a);
+
+ p += 4;
+ }
+ }
+}
+
bool
Image::CreateSurface (const char *fname)
{
@@ -1784,52 +1860,23 @@
surface->width = gdk_pixbuf_get_width (pixbuf);
bool has_alpha = gdk_pixbuf_get_n_channels (pixbuf) == 4;
+ guchar *data;
+ int stride;
if (has_alpha) {
- g_object_ref (pixbuf);
+ surface->backing_pixbuf = pixbuf;
+ surface->backing_data = NULL;
+ unmultiply_rgba_in_place (pixbuf);
+ stride = gdk_pixbuf_get_rowstride (pixbuf);
+ data = gdk_pixbuf_get_pixels (pixbuf);
} else {
- /* gdk-pixbuf packs its pixel data into 24 bits for
- rgb, instead of 32 with an unused byte for alpha,
- like cairo expects */
-
- GdkPixbuf *pb = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
TRUE, 8, surface->width, surface->height);
- gdk_pixbuf_copy_area (pixbuf,
- 0, 0, surface->width,
surface->height,
- pb,
- 0, 0);
+ surface->backing_pixbuf = NULL;
+ surface->backing_data = expand_rgb_to_argb (pixbuf,
&stride);
+ data = surface->backing_data;
g_object_unref (pixbuf);
- pixbuf = pb;
}
- guchar *pb_pixels = gdk_pixbuf_get_pixels (pixbuf);
- guchar *p;
- for (int y = 0; y < surface->height; y ++) {
- p = pb_pixels + y * gdk_pixbuf_get_rowstride (pixbuf);
- for (int x = 0; x < surface->width; x ++) {
- guint32 color = *(guint32*)p;
- guchar r, g, b, a;
-
- get_pixel_bgra (color, b, g, r, a);
-
- /* pre-multipled alpha */
- if (a == 0) {
- r = g = b = 0;
- }
- else if (a < 255) {
- r = pre_multiplied_table [r][a];
- g = pre_multiplied_table [g][a];
- b = pre_multiplied_table [b][a];
- }
-
- /* store it back, swapping red and blue */
- set_pixel_bgra (p, 0, r, g, b, a);
-
- p += 4;
- }
- }
-
- surface->backing_pixbuf = pixbuf;
- surface->cairo = cairo_image_surface_create_for_data (pb_pixels,
+ surface->cairo = cairo_image_surface_create_for_data (data,
#if USE_OPT_RGB24
has_alpha
? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24,
#else
@@ -1837,7 +1884,7 @@
#endif
surface->width,
surface->height,
-
gdk_pixbuf_get_rowstride (pixbuf));
+ stride);
#if USE_OPT_RGB24
surface->has_alpha = has_alpha;
@@ -1897,8 +1944,17 @@
cairo_destroy (cr);
cairo_surface_destroy (surface->cairo);
- g_object_unref (surface->backing_pixbuf);
- surface->backing_pixbuf = NULL;
+
+ if (surface->backing_pixbuf) {
+ g_object_unref (surface->backing_pixbuf);
+ surface->backing_pixbuf = NULL;
+ }
+
+ if (surface->backing_data) {
+ g_free (surface->backing_data);
+ surface->backing_data =NULL;
+ }
+
surface->cairo = xlib_surface;
}
Modified: trunk/moon/src/media.h
===================================================================
--- trunk/moon/src/media.h 2008-02-18 10:52:37 UTC (rev 96043)
+++ trunk/moon/src/media.h 2008-02-18 10:58:03 UTC (rev 96044)
@@ -1,7 +1,9 @@
/*
* media.h:
*
- * Author: Jeffrey Stedfast <[EMAIL PROTECTED]>
+ * Authors:
+ * Jeffrey Stedfast <[EMAIL PROTECTED]>
+ * Michael Dominic K. <[EMAIL PROTECTED]>
*
* Copyright 2007 Novell, Inc. (http://www.novell.com)
*
@@ -117,6 +119,7 @@
cairo_surface_t *cairo;
bool xlib_surface_created;
GdkPixbuf *backing_pixbuf;
+ guchar *backing_data;
bool has_alpha;
int width;
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches