[Swfdec] 3 commits - libswfdec/swfdec_image.c libswfdec/swfdec_image.h

Benjamin Otte company at kemper.freedesktop.org
Sat Nov 10 15:22:02 PST 2007


 libswfdec/swfdec_image.c |  204 ++++++++++++++++++++++++++---------------------
 libswfdec/swfdec_image.h |   11 +-
 2 files changed, 123 insertions(+), 92 deletions(-)

New commits:
commit 54d034a21fa13a6afb4ad788a82b240002def2cf
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Nov 11 00:21:54 2007 +0100

    implement reading from PNG files

diff --git a/libswfdec/swfdec_image.c b/libswfdec/swfdec_image.c
index bff9fa6..0d0362d 100644
--- a/libswfdec/swfdec_image.c
+++ b/libswfdec/swfdec_image.c
@@ -558,10 +558,28 @@ swfdec_image_colormap_decode (SwfdecImage * image,
   }
 }
 
+static cairo_status_t
+swfdec_image_png_read (void *bitsp, unsigned char *data, unsigned int length)
+{
+  SwfdecBits *bits = bitsp;
+  const guint8 *ptr;
+
+  ptr = bits->ptr;
+  if (swfdec_bits_skip_bytes (bits, length) != length)
+    return CAIRO_STATUS_READ_ERROR;
+
+  memcpy (data, ptr, length);
+  return CAIRO_STATUS_SUCCESS;
+}
+
 static void
 swfdec_image_png_load (SwfdecImage *image)
 {
-  SWFDEC_ERROR ("implement loading PNG images");
+  SwfdecBits bits;
+
+  swfdec_bits_init (&bits, image->raw_data);
+  image->surface = cairo_image_surface_create_from_png_stream (
+      swfdec_image_png_read, &bits);
 }
 
 cairo_surface_t *
commit c13bbaaf453acdab1f5189990fe2ff91ed887bc8
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Nov 11 00:15:38 2007 +0100

    get rid of rowstride and data members and decode directly to a surface
    
    This prepares loading PNG files, as we can do this directly with cairo, and
    cairo only hands out surfaces

diff --git a/libswfdec/swfdec_image.c b/libswfdec/swfdec_image.c
index 7dcb879..bff9fa6 100644
--- a/libswfdec/swfdec_image.c
+++ b/libswfdec/swfdec_image.c
@@ -33,6 +33,7 @@
 #include "swfdec_debug.h"
 #include "swfdec_swf_decoder.h"
 
+static const cairo_user_data_key_t key;
 
 static void merge_alpha (SwfdecImage * image, unsigned char *image_data,
     unsigned char *alpha);
@@ -50,10 +51,7 @@ swfdec_image_unload (SwfdecCached *cached)
   if (image->surface) {
     cairo_surface_destroy (image->surface);
     image->surface = NULL;
-  } else if (image->data) {
-    g_free (image->data);
   }
-  image->data = NULL;
 }
 
 static void
@@ -171,25 +169,28 @@ static void
 swfdec_image_jpeg_load (SwfdecImage *image)
 {
   gboolean ret;
+  guint8 *data;
 
   if (image->jpegtables) {
     ret = swfdec_jpeg_decode_argb (
         image->jpegtables->data, image->jpegtables->length,
         image->raw_data->data, image->raw_data->length,
-        (void *)&image->data, &image->width, &image->height);
+        (void *) &data, &image->width, &image->height);
   } else {
     ret = swfdec_jpeg_decode_argb (
         image->raw_data->data, image->raw_data->length,
         NULL, 0,
-        (void *)&image->data, &image->width, &image->height);
+        (void *)&data, &image->width, &image->height);
   }
 
-  if (!ret) {
+  if (!ret)
     return;
-  }
 
   swfdec_cached_load (SWFDEC_CACHED (image), 4 * image->width * image->height);
-  image->rowstride = image->width * 4;
+  image->surface = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_RGB24,
+      image->width, image->height, image->width * 4);
+  cairo_surface_set_user_data (image->surface, &key, data, g_free);
+  cairo_surface_reference (image->surface);
 
   SWFDEC_LOG ("  width = %d", image->width);
   SWFDEC_LOG ("  height = %d", image->height);
@@ -219,16 +220,19 @@ static void
 swfdec_image_jpeg2_load (SwfdecImage *image)
 {
   gboolean ret;
+  guint8 *data;
 
   ret = swfdec_jpeg_decode_argb (image->raw_data->data, image->raw_data->length,
       NULL, 0,
-      (void *)&image->data, &image->width, &image->height);
-  if (!ret) {
+      (void *)&data, &image->width, &image->height);
+  if (!ret)
     return;
-  }
 
   swfdec_cached_load (SWFDEC_CACHED (image), 4 * image->width * image->height);
-  image->rowstride = image->width * 4;
+  image->surface = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_RGB24,
+      image->width, image->height, image->width * 4);
+  cairo_surface_set_user_data (image->surface, &key, data, g_free);
+  cairo_surface_reference (image->surface);
 
   SWFDEC_LOG ("  width = %d", image->width);
   SWFDEC_LOG ("  height = %d", image->height);
@@ -261,6 +265,7 @@ swfdec_image_jpeg3_load (SwfdecImage *image)
   SwfdecBuffer *buffer;
   int jpeg_length;
   gboolean ret;
+  guint8 *data;
 
   swfdec_bits_init (&bits, image->raw_data);
 
@@ -271,19 +276,17 @@ swfdec_image_jpeg3_load (SwfdecImage *image)
 
   ret = swfdec_jpeg_decode_argb (buffer->data, buffer->length,
       NULL, 0,
-      (void *)&image->data, &image->width, &image->height);
+      (void *)&data, &image->width, &image->height);
   swfdec_buffer_unref (buffer);
 
-  if (!ret) {
+  if (!ret)
     return;
-  }
 
   swfdec_cached_load (SWFDEC_CACHED (image), 4 * image->width * image->height);
-  image->rowstride = image->width * 4;
 
   buffer = swfdec_bits_decompress (&bits, -1, image->width * image->height);
   if (buffer) {
-    merge_alpha (image, image->data, buffer->data);
+    merge_alpha (image, data, buffer->data);
     swfdec_buffer_unref (buffer);
   } else {
     SWFDEC_WARNING ("cannot set alpha channel information, decompression failed");
@@ -291,6 +294,11 @@ swfdec_image_jpeg3_load (SwfdecImage *image)
 
   SWFDEC_LOG ("  width = %d", image->width);
   SWFDEC_LOG ("  height = %d", image->height);
+
+  image->surface = cairo_image_surface_create_for_data (data,
+      CAIRO_FORMAT_ARGB32, image->width, image->height, image->width * 4);
+  cairo_surface_set_user_data (image->surface, &key, data, g_free);
+  cairo_surface_reference (image->surface);
 }
 
 static void
@@ -301,7 +309,7 @@ merge_alpha (SwfdecImage * image, unsigned char *image_data,
   unsigned char *p;
 
   for (y = 0; y < image->height; y++) {
-    p = image_data + y * image->rowstride;
+    p = image_data + y * image->width * 4;
     for (x = 0; x < image->width; x++) {
       p[SWFDEC_COLOR_INDEX_ALPHA] = *alpha;
       p += 4;
@@ -317,6 +325,7 @@ swfdec_image_lossless_load (SwfdecImage *image)
   guint color_table_size;
   unsigned char *ptr;
   SwfdecBits bits;
+  guint8 *data;
   int have_alpha = (image->type == SWFDEC_IMAGE_TYPE_LOSSLESS2);
 
   swfdec_bits_init (&bits, image->raw_data);
@@ -348,15 +357,14 @@ swfdec_image_lossless_load (SwfdecImage *image)
     guint i;
     guint rowstride = (image->width + 3) & ~3;
 
-    image->data = g_malloc (4 * image->width * image->height);
-    image->rowstride = image->width * 4;
+    data = g_malloc (4 * image->width * image->height);
 
     if (have_alpha) {
       buffer = swfdec_bits_decompress (&bits, -1, color_table_size * 4 + rowstride * image->height);
       if (buffer == NULL) {
 	SWFDEC_ERROR ("failed to decompress data");
-	memset (image->data, 0, 4 * image->width * image->height);
-	return;
+	memset (data, 0, 4 * image->width * image->height);
+	goto out;
       }
       ptr = buffer->data;
       for (i = 0; i < color_table_size; i++) {
@@ -377,8 +385,8 @@ swfdec_image_lossless_load (SwfdecImage *image)
       buffer = swfdec_bits_decompress (&bits, -1, color_table_size * 3 + rowstride * image->height);
       if (buffer == NULL) {
 	SWFDEC_ERROR ("failed to decompress data");
-	memset (image->data, 0, 4 * image->width * image->height);
-	return;
+	memset (data, 0, 4 * image->width * image->height);
+	goto out;
       }
       ptr = buffer->data;
       for (i = color_table_size - 1; i < color_table_size; i--) {
@@ -400,7 +408,7 @@ swfdec_image_lossless_load (SwfdecImage *image)
       }
       indexed_data = ptr + color_table_size * 3;
     }
-    swfdec_image_colormap_decode (image, image->data, indexed_data,
+    swfdec_image_colormap_decode (image, data, indexed_data,
 	ptr, color_table_size);
 
     swfdec_buffer_unref (buffer);
@@ -416,13 +424,12 @@ swfdec_image_lossless_load (SwfdecImage *image)
     }
 
     buffer = swfdec_bits_decompress (&bits, -1, 2 * ((image->width + 1) & ~1) * image->height);
-    image->data = g_malloc (4 * image->width * image->height);
-    idata = image->data;
-    image->rowstride = image->width * 4;
+    data = g_malloc (4 * image->width * image->height);
+    idata = data;
     if (buffer == NULL) {
       SWFDEC_ERROR ("failed to decompress data");
-      memset (image->data, 0, 4 * image->width * image->height);
-      return;
+      memset (data, 0, 4 * image->width * image->height);
+      goto out;
     }
     ptr = buffer->data;
 
@@ -446,13 +453,12 @@ swfdec_image_lossless_load (SwfdecImage *image)
     SwfdecBuffer *buffer;
     int i, j;
     buffer = swfdec_bits_decompress (&bits, -1, 4 * image->width * image->height);
-    image->rowstride = 4 * image->width;
     if (buffer == NULL) {
       SWFDEC_ERROR ("failed to decompress data");
-      image->data = g_malloc0 (4 * image->width * image->height);
-      return;
+      data = g_malloc0 (4 * image->width * image->height);
+      goto out;
     }
-    ptr = image->data = buffer->data;
+    ptr = data = buffer->data;
     /* image is stored in 0RGB format.  We use ARGB/BGRA. */
     for (j = 0; j < image->height; j++) {
       for (i = 0; i < image->width; i++) {
@@ -466,6 +472,13 @@ swfdec_image_lossless_load (SwfdecImage *image)
     buffer->length = 0;
     swfdec_buffer_unref (buffer);
   }
+
+out:
+  image->surface = cairo_image_surface_create_for_data (data, 
+      have_alpha ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24, 
+      image->width, image->height, image->width * 4);
+  cairo_surface_set_user_data (image->surface, &key, data, g_free);
+  cairo_surface_reference (image->surface);
 }
 
 int
@@ -551,13 +564,13 @@ swfdec_image_png_load (SwfdecImage *image)
   SWFDEC_ERROR ("implement loading PNG images");
 }
 
-static gboolean
-swfdec_image_ensure_loaded (SwfdecImage *image)
+cairo_surface_t *
+swfdec_image_create_surface (SwfdecImage *image)
 {
   if (image->raw_data == NULL)
-    return FALSE;
+    return NULL;
 
-  if (image->data == NULL) {
+  if (image->surface == NULL) {
     switch (image->type) {
       case SWFDEC_IMAGE_TYPE_JPEG:
 	swfdec_image_jpeg_load (image);
@@ -582,60 +595,20 @@ swfdec_image_ensure_loaded (SwfdecImage *image)
 	g_assert_not_reached ();
 	break;
     }
-    if (image->data == NULL) {
-      SWFDEC_WARNING ("failed to load image data");
-      return FALSE;
+    if (image->surface == NULL) {
+      SWFDEC_WARNING ("failed to decode image");
+      return NULL;
     }
   } else {
     swfdec_cached_use (SWFDEC_CACHED (image));
   }
-  return TRUE;
-}
-
-static gboolean
-swfdec_image_has_alpha (SwfdecImage *image)
-{
-  return image->type == SWFDEC_IMAGE_TYPE_LOSSLESS2 ||
-      image->type == SWFDEC_IMAGE_TYPE_JPEG3;
-}
-
-cairo_surface_t *
-swfdec_image_create_surface (SwfdecImage *image)
-{
-  static const cairo_user_data_key_t key;
-
-  g_return_val_if_fail (SWFDEC_IS_IMAGE (image), NULL);
-
-  if (!swfdec_image_ensure_loaded (image))
-    return NULL;
-  if (image->surface) {
-    cairo_surface_reference (image->surface);
-    return image->surface;
-  }
-
-  if (swfdec_image_has_alpha (image)) {
-    cairo_surface_t *surface;
-    guint8 *data;
-    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 
-	image->width, image->height);
-    /* FIXME: only works if rowstride == image->width * 4 */
-    data = cairo_image_surface_get_data (surface);
-    memcpy (data, image->data, image->width * image->height * 4);
-    return surface;
-  } else {
-    image->surface = cairo_image_surface_create_for_data (image->data,
-	CAIRO_FORMAT_RGB24, image->width, image->height, image->rowstride);
-    cairo_surface_set_user_data (image->surface, &key, image->data, g_free);
-    cairo_surface_reference (image->surface);
-    return image->surface;
-  }
+  return cairo_surface_reference (image->surface);
 }
 
 cairo_surface_t *
 swfdec_image_create_surface_transformed (SwfdecImage *image, const SwfdecColorTransform *trans)
 {
-  static const cairo_user_data_key_t key;
-  cairo_surface_t *surface;
+  cairo_surface_t *surface, *source;
   guint8 *tdata;
   const guint8 *sdata;
   guint i, n;
@@ -648,21 +621,21 @@ swfdec_image_create_surface_transformed (SwfdecImage *image, const SwfdecColorTr
   if (swfdec_color_transform_is_identity (trans))
     return swfdec_image_create_surface (image);
 
-  if (!swfdec_image_ensure_loaded (image))
-    return NULL;
-
+  source = swfdec_image_create_surface (image);
   tdata = g_try_malloc (image->width * image->height * 4);
   if (!tdata) {
     SWFDEC_ERROR ("failed to allocate memory for transformed image");
     return NULL;
   }
-  sdata = image->data;
+  /* FIXME: This code assumes a rowstride of 4 * width */
+  sdata = cairo_image_surface_get_data (source);
   n = image->width * image->height;
   for (i = 0; i < n; i++) {
     ((guint32 *) tdata)[i] = swfdec_color_apply_transform_premultiplied (((guint32 *) sdata)[i], trans);
     /* optimization: check for alpha channel to speed up compositing */
     has_alpha = tdata[4 * i + SWFDEC_COLOR_INDEX_ALPHA] != 0xFF;
   }
+  cairo_surface_destroy (source);
   surface = cairo_image_surface_create_for_data (tdata,
       has_alpha ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24, 
       image->width, image->height, image->width * 4);
diff --git a/libswfdec/swfdec_image.h b/libswfdec/swfdec_image.h
index a2b6ba5..9e032ec 100644
--- a/libswfdec/swfdec_image.h
+++ b/libswfdec/swfdec_image.h
@@ -50,11 +50,9 @@ typedef enum {
 struct _SwfdecImage {
   SwfdecCached		cached;
 
-  guint8 *		data;		/* image data in CAIRO_FORMAT_ARGB32 but NOT premultiplied */	
-  int			width;
-  int			height;
-  int			rowstride;
-  cairo_surface_t *	surface;	/* surface that owns the data pointer or NULL (doesn't always work) */
+  int			width;		/* width of image or 0 if not known yet */
+  int			height;		/* height of image or 0 if not known yet */
+  cairo_surface_t *	surface;	/* surface when cache loaded or NULL */
 
   SwfdecImageType	type;
   SwfdecBuffer *	jpegtables;
commit c70f8bcfe8de80b2562359fc44c781789d99442a
Author: Benjamin Otte <otte at gnome.org>
Date:   Sat Nov 10 23:41:50 2007 +0100

    add swfdec_image_new () for images loaded from files
    
    Also adds stubs for PNG loading

diff --git a/libswfdec/swfdec_image.c b/libswfdec/swfdec_image.c
index 4932882..7dcb879 100644
--- a/libswfdec/swfdec_image.c
+++ b/libswfdec/swfdec_image.c
@@ -545,6 +545,12 @@ swfdec_image_colormap_decode (SwfdecImage * image,
   }
 }
 
+static void
+swfdec_image_png_load (SwfdecImage *image)
+{
+  SWFDEC_ERROR ("implement loading PNG images");
+}
+
 static gboolean
 swfdec_image_ensure_loaded (SwfdecImage *image)
 {
@@ -568,6 +574,9 @@ swfdec_image_ensure_loaded (SwfdecImage *image)
       case SWFDEC_IMAGE_TYPE_LOSSLESS2:
 	swfdec_image_lossless_load (image);
 	break;
+      case SWFDEC_IMAGE_TYPE_PNG:
+	swfdec_image_png_load (image);
+	break;
       case SWFDEC_IMAGE_TYPE_UNKNOWN:
       default:
 	g_assert_not_reached ();
@@ -660,3 +669,33 @@ swfdec_image_create_surface_transformed (SwfdecImage *image, const SwfdecColorTr
   cairo_surface_set_user_data (surface, &key, tdata, g_free);
   return surface;
 }
+
+SwfdecImage *
+swfdec_image_new (SwfdecBuffer *buffer)
+{
+  SwfdecImage *image;
+  SwfdecImageType type;
+
+  g_return_val_if_fail (buffer != NULL, NULL);
+
+  /* check type of the image */
+  if (buffer->length < 4)
+    goto fail;
+  if (buffer->data[0] == 0xFF && buffer->data[1] == 0xD8)
+    type = SWFDEC_IMAGE_TYPE_JPEG2;
+  else if (buffer->data[0] == 0xFF && buffer->data[1] == 0xD8 &&
+      buffer->data[0] == 0xFF && buffer->data[1] == 0xD8)
+    type = SWFDEC_IMAGE_TYPE_PNG;
+  else
+    goto fail;
+
+  image = g_object_new (SWFDEC_TYPE_IMAGE, NULL);
+  image->type = type;
+  image->raw_data = buffer;
+
+  return image;
+
+fail:
+  swfdec_buffer_unref (buffer);
+  return NULL;
+}
diff --git a/libswfdec/swfdec_image.h b/libswfdec/swfdec_image.h
index 245c5ed..a2b6ba5 100644
--- a/libswfdec/swfdec_image.h
+++ b/libswfdec/swfdec_image.h
@@ -43,6 +43,8 @@ typedef enum {
   SWFDEC_IMAGE_TYPE_JPEG3,
   SWFDEC_IMAGE_TYPE_LOSSLESS,
   SWFDEC_IMAGE_TYPE_LOSSLESS2,
+  /* those can only be created by loading from files */
+  SWFDEC_IMAGE_TYPE_PNG
 } SwfdecImageType;
 
 struct _SwfdecImage {
@@ -66,6 +68,7 @@ struct _SwfdecImageClass {
 
 GType			swfdec_image_get_type		(void);
 
+SwfdecImage *		swfdec_image_new		(SwfdecBuffer *		buffer);
 cairo_surface_t *	swfdec_image_create_surface	(SwfdecImage *		image);
 cairo_surface_t *	swfdec_image_create_surface_transformed 
 							(SwfdecImage *		image,


More information about the Swfdec mailing list