Benjamin Otte
2007-Nov-10 23:22 UTC
[Swfdec] 3 commits - libswfdec/swfdec_image.c libswfdec/swfdec_image.h
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,
Riccardo Magliocchetti
2007-Nov-11 09:07 UTC
[Swfdec] 3 commits - libswfdec/swfdec_image.c libswfdec/swfdec_image.h
On Sat, 10 Nov 2007 15:22:02 -0800 (PST) company at kemper.freedesktop.org (Benjamin Otte) wrote:> 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[snip]> @@ -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;I think you forgot to update the png test. thanks, Riccardo
Seemingly Similar Threads
- Branch 'interpreter' - 8 commits - libswfdec/swfdec_bits.c libswfdec/swfdec_color.c libswfdec/swfdec_color.h libswfdec/swfdec_edittext.c libswfdec/swfdec_image.c libswfdec/swfdec_image.h libswfdec/swfdec_pattern.c libswfdec/swfdec_sprite.c test/dump.c
- 21 commits - configure.ac libswfdec/swfdec_audio_event.c libswfdec/swfdec_bits.c libswfdec/swfdec_button_movie.c libswfdec/swfdec_color.c libswfdec/swfdec_color.h libswfdec/swfdec_compiler.c libswfdec/swfdec_edittext.c libswfdec/swfdec_image.c
- Branch 'interpreter' - 18 commits - libswfdec/swfdec_image.c libswfdec/swfdec_image.h libswfdec/swfdec_js.c libswfdec/swfdec_js_color.c libswfdec/swfdec_js_sound.c libswfdec/swfdec_pattern.c libswfdec/swfdec_scriptable.c libswfdec/swfdec_script.c
- libswfdec/swfdec_image.c libswfdec/swfdec_image.h libswfdec/swfdec_pattern.c
- 5 commits - libswfdec/jpeg libswfdec/swfdec_as_interpret.c libswfdec/swfdec_bits.c libswfdec/swfdec_cached.c libswfdec/swfdec_codec_adpcm.c libswfdec/swfdec_codec_audio.c libswfdec/swfdec_flash_security.c libswfdec/swfdec_image.c