diff options
author | Matthias Clasen <matthiasc@src.gnome.org> | 2002-07-06 23:10:46 +0000 |
---|---|---|
committer | Matthias Clasen <matthiasc@src.gnome.org> | 2002-07-06 23:10:46 +0000 |
commit | e4ab3810185b6eda9651f0f03d017893b906b868 (patch) | |
tree | f39efe2ad114a15e3e44ba74bc83c396b4207f66 | |
parent | 09487ff9f537152473cfed4ee3afe450606e60b4 (diff) | |
download | gtk+-e4ab3810185b6eda9651f0f03d017893b906b868.tar.gz |
Load-at-size functionality for gdk-pixbuf.
-rw-r--r-- | docs/reference/ChangeLog | 7 | ||||
-rw-r--r-- | docs/reference/gdk-pixbuf/Makefile.am | 2 | ||||
-rw-r--r-- | docs/reference/gdk-pixbuf/gdk-pixbuf-sections.txt | 2 | ||||
-rw-r--r-- | docs/reference/gdk-pixbuf/tmpl/gdk-pixbuf-loader.sgml | 58 | ||||
-rw-r--r-- | docs/reference/gdk-pixbuf/tmpl/module_interface.sgml | 18 | ||||
-rw-r--r-- | gdk-pixbuf/ChangeLog | 31 | ||||
-rw-r--r-- | gdk-pixbuf/gdk-pixbuf-io.h | 7 | ||||
-rw-r--r-- | gdk-pixbuf/gdk-pixbuf-loader.c | 141 | ||||
-rw-r--r-- | gdk-pixbuf/gdk-pixbuf-loader.h | 10 | ||||
-rw-r--r-- | gdk-pixbuf/gdk-pixbuf-marshal.list | 1 | ||||
-rw-r--r-- | gdk-pixbuf/io-bmp.c | 8 | ||||
-rw-r--r-- | gdk-pixbuf/io-gif.c | 3 | ||||
-rw-r--r-- | gdk-pixbuf/io-ico.c | 8 | ||||
-rw-r--r-- | gdk-pixbuf/io-jpeg.c | 87 | ||||
-rw-r--r-- | gdk-pixbuf/io-png.c | 3 | ||||
-rw-r--r-- | gdk-pixbuf/io-pnm.c | 6 | ||||
-rw-r--r-- | gdk-pixbuf/io-ras.c | 8 | ||||
-rw-r--r-- | gdk-pixbuf/io-tga.c | 3 | ||||
-rw-r--r-- | gdk-pixbuf/io-tiff.c | 3 | ||||
-rw-r--r-- | gdk-pixbuf/io-wbmp.c | 8 | ||||
-rw-r--r-- | gdk-pixbuf/io-xbm.c | 3 | ||||
-rw-r--r-- | gdk-pixbuf/io-xpm.c | 3 |
22 files changed, 313 insertions, 107 deletions
diff --git a/docs/reference/ChangeLog b/docs/reference/ChangeLog index 8bb545817b..0f75a3466c 100644 --- a/docs/reference/ChangeLog +++ b/docs/reference/ChangeLog @@ -1,3 +1,10 @@ +2002-07-07 Matthias Clasen <maclas@gmx.de> + + * gdk-pixbuf/gdk-pixbuf-sections.txt, + gdk-pixbuf/tmpl/gdk-pixbuf-loader.sgml, + gdk-pixbuf/tmpl/module_interface.sgml: Updates for + load-at-size functionality. + Tue Jun 18 17:02:48 2002 Owen Taylor <otaylor@redhat.com> * gdk/gdk-sections.txt: Fix for cursor screen => display diff --git a/docs/reference/gdk-pixbuf/Makefile.am b/docs/reference/gdk-pixbuf/Makefile.am index aa568b9840..1f9a3f36c1 100644 --- a/docs/reference/gdk-pixbuf/Makefile.am +++ b/docs/reference/gdk-pixbuf/Makefile.am @@ -13,7 +13,7 @@ DOC_SOURCE_DIR=../../../gdk-pixbuf SCAN_OPTIONS=--source-dir=../../../contrib/gdk-pixbuf-xlib --deprecated-guards="GDK_PIXBUF_ENABLE_BROKEN|GDK_PIXBUF_DISABLE_DEPRECATED" # Extra options to supply to gtkdoc-mkdb -MKDB_OPTIONS=--sgml-mode --source-dir=../../../contrib/gdk-pixbuf-xlib --output-format=xml +MKDB_OPTIONS=--main-sgml-file=$(DOC_MAIN_SGML_FILE) --sgml-mode --source-dir=../../../contrib/gdk-pixbuf-xlib --output-format=xml # Extra options to supply to gtkdoc-fixref FIXXREF_OPTIONS= diff --git a/docs/reference/gdk-pixbuf/gdk-pixbuf-sections.txt b/docs/reference/gdk-pixbuf/gdk-pixbuf-sections.txt index a41778b36e..1f5af2b87d 100644 --- a/docs/reference/gdk-pixbuf/gdk-pixbuf-sections.txt +++ b/docs/reference/gdk-pixbuf/gdk-pixbuf-sections.txt @@ -149,6 +149,7 @@ gdk_interp_type_get_type gdk_pixbuf_loader_new gdk_pixbuf_loader_new_with_type gdk_pixbuf_loader_write +gdk_pixbuf_loader_set_size gdk_pixbuf_loader_get_pixbuf gdk_pixbuf_loader_get_animation gdk_pixbuf_loader_close @@ -168,6 +169,7 @@ gdk_pixbuf_loader_get_type <TITLE>Module Interface</TITLE> <FILE>module_interface</FILE> ModuleFillVtableFunc +ModuleSizeFunc ModulePreparedNotifyFunc ModuleUpdatedNotifyFunc GdkPixbufModule diff --git a/docs/reference/gdk-pixbuf/tmpl/gdk-pixbuf-loader.sgml b/docs/reference/gdk-pixbuf/tmpl/gdk-pixbuf-loader.sgml index dbdfa95c20..fb6275b5ed 100644 --- a/docs/reference/gdk-pixbuf/tmpl/gdk-pixbuf-loader.sgml +++ b/docs/reference/gdk-pixbuf/tmpl/gdk-pixbuf-loader.sgml @@ -21,21 +21,28 @@ Application-driven progressive image loading. To use #GdkPixbufLoader to load an image, just create a new one, and call gdk_pixbuf_loader_write() to send the data to it. When done, gdk_pixbuf_loader_close() should be called to end the stream - and finalize everything. The loader will emit two important + and finalize everything. The loader will emit three important signals throughout the process. The first, "<link - linkend="GdkPixbufLoader-area-prepared">area_prepared</link>", + linkend="GdkPixbufLoader-size-prepared">size_prepared</link>", will be called as soon as the image has enough information to - determine the size of the image to be used. It will pass a - @GdkPixbuf in. If you want to use it, you can simply ref it. In - addition, no actual information will be passed in yet, so the + determine the size of the image to be used. If you want to scale + the image while loading it, you can call gdk_pixbuf_loader_set_size() + in response to this signal. + </para> + + <para>The second signal, "<link + linkend="GdkPixbufLoader-area-prepared">area_prepared</link>", + will be called as soon as the pixbuf of the desired has been + allocated. You can obtain it by calling gdk_pixbuf_loader_get_pixbuf(). + If you want to use it, simply ref it. + In addition, no actual information will be passed in yet, so the pixbuf can be safely filled with any temporary graphics (or an - initial color) as needed. You can also call the - gdk_pixbuf_loader_get_pixbuf() once this signal has been emitted - and get the same pixbuf. + initial color) as needed. You can also call + gdk_pixbuf_loader_get_pixbuf() later and get the same pixbuf. </para> <para> - The other signal, "<link + The last signal, "<link linkend="GdkPixbufLoader-area-updated">area_updated</link>" gets called every time a region is updated. This way you can update a partially completed image. Note that you do not know anything @@ -119,19 +126,23 @@ Application-driven progressive image loading. @error: @Returns: - -<!-- ##### SIGNAL GdkPixbufLoader::area-prepared ##### --> +<!-- ##### SIGNAL GdkPixbufLoader::size-prepared ##### --> <para> This signal is emitted when the pixbuf loader has been fed the - initial amount of data that is required to figure out the size and - format of the image that it will create. After this signal is - emitted, applications can call gdk_pixbuf_loader_get_pixbuf() to - fetch the partially-loaded pixbuf. + initial amount of data that is required to figure out the size + of the image that it will create. Applications can call + gdk_pixbuf_loader_set_size() in response to this signal to set + the desired size to which the image should be scaled. </para> +@width: the original width of the image +@height: the original height of the image -@gdkpixbufloader: the object which received the signal. -<!-- # Unused Parameters # --> -@loader: Loader which emitted the signal. +<!-- ##### SIGNAL GdkPixbufLoader::area-prepared ##### --> + <para> + This signal is emitted when the pixbuf loader has allocated the pixbuf + in the desired size. After this signal is emitted, applications can + call gdk_pixbuf_loader_get_pixbuf() to fetch the partially-loaded pixbuf. + </para> <!-- ##### SIGNAL GdkPixbufLoader::area-updated ##### --> <para> @@ -142,13 +153,7 @@ Application-driven progressive image loading. areas of an image that is being loaded. </para> -@gdkpixbufloader: the object which received the signal. -@arg1: -@arg2: -@arg3: -@arg4: -<!-- # Unused Parameters # --> -@loader: Loader which emitted the signal. +@gdkpixbufloader: Loader which emitted the signal. @x: X offset of upper-left corner of the updated area. @y: Y offset of upper-left corner of the updated area. @width: Width of updated area. @@ -163,8 +168,6 @@ Application-driven progressive image loading. </para> @gdkpixbufloader: the object which received the signal. -<!-- # Unused Parameters # --> -@loader: Loader which emitted the signal. <!-- Local variables: @@ -173,3 +176,4 @@ sgml-parent-document: ("../gdk-pixbuf.sgml" "book" "refsect2" "") End: --> + diff --git a/docs/reference/gdk-pixbuf/tmpl/module_interface.sgml b/docs/reference/gdk-pixbuf/tmpl/module_interface.sgml index 028041b871..5dd76877c5 100644 --- a/docs/reference/gdk-pixbuf/tmpl/module_interface.sgml +++ b/docs/reference/gdk-pixbuf/tmpl/module_interface.sgml @@ -23,6 +23,24 @@ Defines the type of the function used to set the vtable of a @module: a #GdkPixbufModule. +<!-- ##### USER_FUNCTION ModuleSizeFunc ##### --> +<para> +Defines the type of the function that gets called once the size +of the loaded image is known is done. +</para> +<para> +The function is expected to set @width and @height to the desired +size to which the image should be scaled. If a module has no efficient +way to achieve the desired scaling during the loading of the image, it may +either ignore the size request, or only approximate it -- the loader will +then perform the required scaling on the completely loaded image. +</para> + +@width: pointer to a location containing the current image width +@height: pointer to a location containing the current image height +@user_data: the loader. + + <!-- ##### USER_FUNCTION ModulePreparedNotifyFunc ##### --> <para> Defines the type of the function that gets called once the initial diff --git a/gdk-pixbuf/ChangeLog b/gdk-pixbuf/ChangeLog index f72862b77d..b0d6ab4b4b 100644 --- a/gdk-pixbuf/ChangeLog +++ b/gdk-pixbuf/ChangeLog @@ -1,3 +1,34 @@ +2002-07-07 Matthias Clasen <maclas@gmx.de> + + Load-at-size functionality (#53726): + + * gdk-pixbuf-io.h (ModuleSizeFunc): New. + (_GdkPixbufModule): Prepend a ModuleSizeFunc to the + begin_load arguments. Adjust all modules. + * gdk-pixbuf-loader.c (struct GdkPixbufLoaderPrivate): Add + fields width, height, size_fixed, need_scale. + (gdk_pixbuf_loader_class_init): Add size_prepared signal. + (gdk_pixbuf_loader_set_size): New function. + (gdk_pixbuf_loader_size_func): ModuleSizeFunc which gets + passed to the module, emits size_prepared. + (gdk_pixbuf_loader_prepare): Call gdk_pixbuf_loader_size_func + if necessary, only emit area_prepared if no separate scaling + is required. + (gdk_pixbuf_loader_update): Only emit area_updated if no + separate scaling is required. + (gdk_pixbuf_loader_load_module): Add size_func as first argument. + (gdk_pixbuf_loader_close): If necessary scale the image + to the desired size and emit area_prepared and area_updated. + * gdk-pixbuf-loader.h (struct _GdkPixbufLoaderClass): Add + size_prepared signal. + (gdk_pixbuf_loader_set_size) New API. + * gdk-pixbuf-marshal.list: Add VOID:INT,INT. + * io-jpeg.c: User cinfo->output_width/height instead of + cinfo->image_width/height throughout when adressing the pixbuf. + (gdk_pixbuf__jpeg_image_load_increment): Call size_func, and + find the nearest possible output size which libjpeg can produce + that is still larger than the desired size. + 2002-07-06 Matthias Clasen <maclas@gmx.de> * io-tiff.c (tiff_set_error): Handle global_error == NULL diff --git a/gdk-pixbuf/gdk-pixbuf-io.h b/gdk-pixbuf/gdk-pixbuf-io.h index 15e9de0a0f..8cf233fe26 100644 --- a/gdk-pixbuf/gdk-pixbuf-io.h +++ b/gdk-pixbuf/gdk-pixbuf-io.h @@ -37,6 +37,10 @@ G_BEGIN_DECLS +typedef void (* ModuleSizeFunc) (gint *width, + gint *height, + gpointer user_data); + typedef void (* ModulePreparedNotifyFunc) (GdkPixbuf *pixbuf, GdkPixbufAnimation *anim, gpointer user_data); @@ -58,7 +62,8 @@ struct _GdkPixbufModule { /* Incremental loading */ - gpointer (* begin_load) (ModulePreparedNotifyFunc prepare_func, + gpointer (* begin_load) (ModuleSizeFunc size_func, + ModulePreparedNotifyFunc prepare_func, ModuleUpdatedNotifyFunc update_func, gpointer user_data, GError **error); diff --git a/gdk-pixbuf/gdk-pixbuf-loader.c b/gdk-pixbuf/gdk-pixbuf-loader.c index 52b1f112a6..bcb7382e32 100644 --- a/gdk-pixbuf/gdk-pixbuf-loader.c +++ b/gdk-pixbuf/gdk-pixbuf-loader.c @@ -31,8 +31,9 @@ #include "gdk-pixbuf-marshal.h" enum { - AREA_UPDATED, + SIZE_PREPARED, AREA_PREPARED, + AREA_UPDATED, CLOSED, LAST_SIGNAL }; @@ -58,6 +59,10 @@ typedef struct gint header_buf_offset; GdkPixbufModule *image_module; gpointer context; + gint width; + gint height; + gboolean size_fixed; + gboolean needs_scale; } GdkPixbufLoaderPrivate; @@ -109,6 +114,17 @@ gdk_pixbuf_loader_class_init (GdkPixbufLoaderClass *class) object_class->finalize = gdk_pixbuf_loader_finalize; + pixbuf_loader_signals[SIZE_PREPARED] = + g_signal_new ("size_prepared", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GdkPixbufLoaderClass, size_prepared), + NULL, NULL, + gdk_pixbuf_marshal_VOID__INT_INT, + G_TYPE_NONE, 2, + G_TYPE_INT, + G_TYPE_INT); + pixbuf_loader_signals[AREA_PREPARED] = g_signal_new ("area_prepared", G_TYPE_FROM_CLASS (object_class), @@ -170,14 +186,73 @@ gdk_pixbuf_loader_finalize (GObject *object) G_OBJECT_CLASS (parent_class)->finalize (object); } +/** + * gdk_pixbuf_loader_set_size: + * @loader: A pixbuf loader. + * @width: The desired width of the image being loaded. + * @height: The desired height of the image being loaded. + * + * Causes the image to be scaled while it is loaded. The desired + * image size can be determined relative to the original size of + * the image by calling gdk_pixbuf_loader_set_size() from a + * signal handler for the ::size_prepared signal. + * + * Attempts to set the desired image size are ignored after the + * emission of the ::size_prepared signal. + */ +void +gdk_pixbuf_loader_set_size (GdkPixbufLoader *loader, + gint width, + gint height) +{ + GdkPixbufLoaderPrivate *priv = GDK_PIXBUF_LOADER (loader)->priv; + g_return_if_fail (width > 0 && height > 0); + + if (!priv->size_fixed) { + priv->width = width; + priv->height = height; + } +} + +static void +gdk_pixbuf_loader_size_func (gint *width, gint *height, gpointer loader) +{ + GdkPixbufLoaderPrivate *priv = GDK_PIXBUF_LOADER (loader)->priv; + + /* allow calling gdk_pixbuf_loader_set_size() before the signal */ + if (priv->width == 0 && priv->height == 0) { + priv->width = *width; + priv->height = *height; + } + + g_signal_emit (loader, pixbuf_loader_signals[SIZE_PREPARED], 0, *width, *height); + priv->size_fixed = TRUE; + + *width = priv->width; + *height = priv->height; +} + static void gdk_pixbuf_loader_prepare (GdkPixbuf *pixbuf, GdkPixbufAnimation *anim, gpointer loader) { - GdkPixbufLoaderPrivate *priv = NULL; - - priv = GDK_PIXBUF_LOADER (loader)->priv; + GdkPixbufLoaderPrivate *priv = GDK_PIXBUF_LOADER (loader)->priv; + g_return_if_fail (pixbuf != NULL); + + if (!priv->size_fixed) { + /* Defend against lazy loaders which don't call size_func */ + gint width = gdk_pixbuf_get_width (pixbuf); + gint height = gdk_pixbuf_get_height (pixbuf); + + gdk_pixbuf_loader_size_func (&width, &height, loader); + } + + priv->needs_scale = FALSE; + if (priv->width > 0 && priv->height > 0 && + (priv->width != gdk_pixbuf_get_width (pixbuf) || + priv->height != gdk_pixbuf_get_height (pixbuf))) + priv->needs_scale = TRUE; if (anim) g_object_ref (anim); @@ -186,7 +261,8 @@ gdk_pixbuf_loader_prepare (GdkPixbuf *pixbuf, priv->animation = anim; - g_signal_emit (loader, pixbuf_loader_signals[AREA_PREPARED], 0); + if (!priv->needs_scale) + g_signal_emit (loader, pixbuf_loader_signals[AREA_PREPARED], 0); } static void @@ -197,17 +273,16 @@ gdk_pixbuf_loader_update (GdkPixbuf *pixbuf, gint height, gpointer loader) { - GdkPixbufLoaderPrivate *priv = NULL; - - priv = GDK_PIXBUF_LOADER (loader)->priv; - - g_signal_emit (loader, - pixbuf_loader_signals[AREA_UPDATED], - 0, - x, y, - /* sanity check in here. Defend against an errant loader */ - MIN (width, gdk_pixbuf_animation_get_width (priv->animation)), - MIN (height, gdk_pixbuf_animation_get_height (priv->animation))); + GdkPixbufLoaderPrivate *priv = GDK_PIXBUF_LOADER (loader)->priv; + + if (!priv->needs_scale) + g_signal_emit (loader, + pixbuf_loader_signals[AREA_UPDATED], + 0, + x, y, + /* sanity check in here. Defend against an errant loader */ + MIN (width, gdk_pixbuf_animation_get_width (priv->animation)), + MIN (height, gdk_pixbuf_animation_get_height (priv->animation))); } static gint @@ -253,10 +328,11 @@ gdk_pixbuf_loader_load_module (GdkPixbufLoader *loader, return 0; } - priv->context = priv->image_module->begin_load (gdk_pixbuf_loader_prepare, - gdk_pixbuf_loader_update, - loader, - error); + priv->context = priv->image_module->begin_load (gdk_pixbuf_loader_size_func, + gdk_pixbuf_loader_prepare, + gdk_pixbuf_loader_update, + loader, + error); if (priv->context == NULL) { @@ -536,12 +612,33 @@ gdk_pixbuf_loader_close (GdkPixbufLoader *loader, retval = FALSE; } } + if (priv->image_module && priv->image_module->stop_load && priv->context) { if (!priv->image_module->stop_load (priv->context, error)) retval = FALSE; } priv->closed = TRUE; + + if (priv->needs_scale) { + GdkPixbuf *tmp, *pixbuf; + + tmp = gdk_pixbuf_animation_get_static_image (priv->animation); + g_object_ref (tmp); + pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, tmp->has_alpha, 8, priv->width, priv->height); + g_object_unref (priv->animation); + priv->animation = gdk_pixbuf_non_anim_new (pixbuf); + g_signal_emit (loader, pixbuf_loader_signals[AREA_PREPARED], 0); + gdk_pixbuf_scale (tmp, pixbuf, 0, 0, priv->width, priv->height, 0, 0, + (double) priv->width / tmp->width, + (double) priv->height / tmp->height, + GDK_INTERP_BILINEAR); + g_object_unref (tmp); + + g_signal_emit (loader, pixbuf_loader_signals[AREA_UPDATED], 0, + 0, 0, priv->width, priv->height); + } + g_signal_emit (loader, pixbuf_loader_signals[CLOSED], 0); @@ -549,3 +646,7 @@ gdk_pixbuf_loader_close (GdkPixbufLoader *loader, } + + + + diff --git a/gdk-pixbuf/gdk-pixbuf-loader.h b/gdk-pixbuf/gdk-pixbuf-loader.h index bacaf9d38c..030d446fa1 100644 --- a/gdk-pixbuf/gdk-pixbuf-loader.h +++ b/gdk-pixbuf/gdk-pixbuf-loader.h @@ -50,6 +50,10 @@ struct _GdkPixbufLoaderClass { GObjectClass parent_class; + void (*size_prepared) (GdkPixbufLoader *loader, + int width, + int height); + void (*area_prepared) (GdkPixbufLoader *loader); /* Last known frame needs a redraw for x, y, width, height */ @@ -62,11 +66,13 @@ struct _GdkPixbufLoaderClass void (*closed) (GdkPixbufLoader *loader); }; - GType gdk_pixbuf_loader_get_type (void) G_GNUC_CONST; GdkPixbufLoader * gdk_pixbuf_loader_new (void); GdkPixbufLoader * gdk_pixbuf_loader_new_with_type (const char *image_type, GError **error); +void gdk_pixbuf_loader_set_size (GdkPixbufLoader *loader, + int width, + int height); gboolean gdk_pixbuf_loader_write (GdkPixbufLoader *loader, const guchar *buf, gsize count, @@ -80,3 +86,5 @@ gboolean gdk_pixbuf_loader_close (GdkPixbufLoader *loader, G_END_DECLS #endif + + diff --git a/gdk-pixbuf/gdk-pixbuf-marshal.list b/gdk-pixbuf/gdk-pixbuf-marshal.list index db100651bb..9e63f91c4f 100644 --- a/gdk-pixbuf/gdk-pixbuf-marshal.list +++ b/gdk-pixbuf/gdk-pixbuf-marshal.list @@ -25,3 +25,4 @@ VOID:VOID VOID:INT,INT,INT,INT VOID:POINTER +VOID:INT,INT diff --git a/gdk-pixbuf/io-bmp.c b/gdk-pixbuf/io-bmp.c index 8b0e3c07df..83df835f3d 100644 --- a/gdk-pixbuf/io-bmp.c +++ b/gdk-pixbuf/io-bmp.c @@ -181,7 +181,8 @@ struct bmp_progressive_state { }; static gpointer -gdk_pixbuf__bmp_image_begin_load(ModulePreparedNotifyFunc prepared_func, +gdk_pixbuf__bmp_image_begin_load(ModuleSizeFunc size_func, + ModulePreparedNotifyFunc prepared_func, ModuleUpdatedNotifyFunc updated_func, gpointer user_data, GError **error); @@ -205,7 +206,7 @@ static GdkPixbuf *gdk_pixbuf__bmp_image_load(FILE * f, GError **error) GdkPixbuf *pb; State = - gdk_pixbuf__bmp_image_begin_load(NULL, NULL, NULL, + gdk_pixbuf__bmp_image_begin_load(NULL, NULL, NULL, NULL, error); if (State == NULL) @@ -512,7 +513,8 @@ decode_bitmasks (guchar *buf, */ static gpointer -gdk_pixbuf__bmp_image_begin_load(ModulePreparedNotifyFunc prepared_func, +gdk_pixbuf__bmp_image_begin_load(ModuleSizeFunc size_func, + ModulePreparedNotifyFunc prepared_func, ModuleUpdatedNotifyFunc updated_func, gpointer user_data, GError **error) diff --git a/gdk-pixbuf/io-gif.c b/gdk-pixbuf/io-gif.c index 09c843e840..b85e2ea958 100644 --- a/gdk-pixbuf/io-gif.c +++ b/gdk-pixbuf/io-gif.c @@ -1396,7 +1396,8 @@ gdk_pixbuf__gif_image_load (FILE *file, GError **error) } static gpointer -gdk_pixbuf__gif_image_begin_load (ModulePreparedNotifyFunc prepare_func, +gdk_pixbuf__gif_image_begin_load (ModuleSizeFunc size_func, + ModulePreparedNotifyFunc prepare_func, ModuleUpdatedNotifyFunc update_func, gpointer user_data, GError **error) diff --git a/gdk-pixbuf/io-ico.c b/gdk-pixbuf/io-ico.c index bac4d8e907..1a1de441e4 100644 --- a/gdk-pixbuf/io-ico.c +++ b/gdk-pixbuf/io-ico.c @@ -158,7 +158,8 @@ struct ico_progressive_state { }; static gpointer -gdk_pixbuf__ico_image_begin_load(ModulePreparedNotifyFunc prepared_func, +gdk_pixbuf__ico_image_begin_load(ModuleSizeFunc size_func, + ModulePreparedNotifyFunc prepared_func, ModuleUpdatedNotifyFunc updated_func, gpointer user_data, GError **error); @@ -193,7 +194,7 @@ gdk_pixbuf__ico_image_load(FILE * f, GError **error) GdkPixbuf *pb; - State = gdk_pixbuf__ico_image_begin_load(NULL, NULL, NULL, error); + State = gdk_pixbuf__ico_image_begin_load(NULL, NULL, NULL, NULL, error); if (State == NULL) return NULL; @@ -478,7 +479,8 @@ static void DecodeHeader(guchar *Data, gint Bytes, */ static gpointer -gdk_pixbuf__ico_image_begin_load(ModulePreparedNotifyFunc prepared_func, +gdk_pixbuf__ico_image_begin_load(ModuleSizeFunc size_func, + ModulePreparedNotifyFunc prepared_func, ModuleUpdatedNotifyFunc updated_func, gpointer user_data, GError **error) diff --git a/gdk-pixbuf/io-jpeg.c b/gdk-pixbuf/io-jpeg.c index 0081402e83..9641099422 100644 --- a/gdk-pixbuf/io-jpeg.c +++ b/gdk-pixbuf/io-jpeg.c @@ -1,3 +1,4 @@ +/* -*- mode: C; c-file-style: "linux" -*- */ /* GdkPixbuf library - JPEG image loader * * Copyright (C) 1999 Michael Zucchi @@ -50,7 +51,7 @@ typedef struct { JOCTET buffer[JPEG_PROG_BUF_SIZE]; /* start of buffer */ long skip_next; /* number of bytes to skip next read */ - + } my_source_mgr; typedef my_source_mgr * my_src_ptr; @@ -64,6 +65,7 @@ struct error_handler_data { /* progressive loader context */ typedef struct { + ModuleSizeFunc size_func; ModuleUpdatedNotifyFunc updated_func; ModulePreparedNotifyFunc prepared_func; gpointer user_data; @@ -80,7 +82,8 @@ typedef struct { } JpegProgContext; static GdkPixbuf *gdk_pixbuf__jpeg_image_load (FILE *f, GError **error); -static gpointer gdk_pixbuf__jpeg_image_begin_load (ModulePreparedNotifyFunc func, +static gpointer gdk_pixbuf__jpeg_image_begin_load (ModuleSizeFunc func0, + ModulePreparedNotifyFunc func1, ModuleUpdatedNotifyFunc func2, gpointer user_data, GError **error); @@ -140,7 +143,7 @@ explode_gray_into_buf (struct jpeg_decompress_struct *cinfo, /* Expand grey->colour. Expand from the end of the * memory down, so we can use the same buffer. */ - w = cinfo->image_width; + w = cinfo->output_width; for (i = cinfo->rec_outbuf_height - 1; i >= 0; i--) { guchar *from, *to; @@ -171,7 +174,7 @@ convert_cmyk_to_rgb (struct jpeg_decompress_struct *cinfo, guchar *p; p = lines[i]; - for (j = 0; j < cinfo->image_width; j++) { + for (j = 0; j < cinfo->output_width; j++) { int c, m, y, k; c = p[0]; m = p[1]; @@ -446,8 +449,9 @@ skip_input_data (j_decompress_ptr cinfo, long num_bytes) */ gpointer -gdk_pixbuf__jpeg_image_begin_load (ModulePreparedNotifyFunc prepared_func, - ModuleUpdatedNotifyFunc updated_func, +gdk_pixbuf__jpeg_image_begin_load (ModuleSizeFunc size_func, + ModulePreparedNotifyFunc prepared_func, + ModuleUpdatedNotifyFunc updated_func, gpointer user_data, GError **error) { @@ -455,6 +459,7 @@ gdk_pixbuf__jpeg_image_begin_load (ModulePreparedNotifyFunc prepared_func, my_source_mgr *src; context = g_new0 (JpegProgContext, 1); + context->size_func = size_func; context->prepared_func = prepared_func; context->updated_func = updated_func; context->user_data = user_data; @@ -469,11 +474,11 @@ gdk_pixbuf__jpeg_image_begin_load (ModulePreparedNotifyFunc prepared_func, context->cinfo.src = (struct jpeg_source_mgr *) g_try_malloc (sizeof (my_source_mgr)); if (!context->cinfo.src) { - g_set_error (error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, - _("Couldn't allocate memory for loading JPEG file")); - return NULL; + g_set_error (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, + _("Couldn't allocate memory for loading JPEG file")); + return NULL; } memset (context->cinfo.src, 0, sizeof (my_source_mgr)); @@ -509,14 +514,14 @@ gdk_pixbuf__jpeg_image_stop_load (gpointer data, GError **error) JpegProgContext *context = (JpegProgContext *) data; g_return_val_if_fail (context != NULL, TRUE); - + /* FIXME this thing needs to report errors if * we have unused image data */ if (context->pixbuf) g_object_unref (context->pixbuf); - + /* if we have an error? */ if (sigsetjmp (context->jerr.setjmp_buffer, 1)) { jpeg_destroy_decompress (&context->cinfo); @@ -559,6 +564,7 @@ gdk_pixbuf__jpeg_image_load_increment (gpointer data, guint spinguard; gboolean first; const guchar *bufhd; + gint width, height; g_return_val_if_fail (context != NULL, FALSE); g_return_val_if_fail (buf != NULL, FALSE); @@ -569,10 +575,6 @@ gdk_pixbuf__jpeg_image_load_increment (gpointer data, context->jerr.error = error; - /* XXXXXXX (drmike) - loop(s) below need to be recoded now I - * have a grasp of what the flow needs to be! - */ - /* check for fatal error */ if (sigsetjmp (context->jerr.setjmp_buffer, 1)) { return FALSE; @@ -636,29 +638,32 @@ gdk_pixbuf__jpeg_image_load_increment (gpointer data, /* try to load jpeg header */ if (!context->got_header) { int rc; - + rc = jpeg_read_header (cinfo, TRUE); context->src_initialized = TRUE; - + if (rc == JPEG_SUSPENDED) continue; - + context->got_header = TRUE; - - } else if (!context->did_prescan) { - int rc; - /* start decompression */ - cinfo->buffered_image = TRUE; - rc = jpeg_start_decompress (cinfo); - cinfo->do_fancy_upsampling = FALSE; - cinfo->do_block_smoothing = FALSE; - - context->pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, - cinfo->output_components == 4 ? TRUE : FALSE, - 8, - cinfo->image_width, - cinfo->image_height); + width = cinfo->image_width; + height = cinfo->image_height; + (* context->size_func) (&width, &height, context->user_data); + for (cinfo->scale_denom = 2; cinfo->scale_denom <= 8; cinfo->scale_denom *= 2) { + jpeg_calc_output_dimensions (cinfo); + if (cinfo->output_width < width || cinfo->output_height < height) { + cinfo->scale_denom /= 2; + break; + } + } + jpeg_calc_output_dimensions (cinfo); + + context->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, + cinfo->output_components == 4 ? TRUE : FALSE, + 8, + cinfo->output_width, + cinfo->output_height); if (context->pixbuf == NULL) { g_set_error (error, @@ -667,16 +672,24 @@ gdk_pixbuf__jpeg_image_load_increment (gpointer data, _("Couldn't allocate memory for loading JPEG file")); return FALSE; } - + /* Use pixbuf buffer to store decompressed data */ context->dptr = context->pixbuf->pixels; - + /* Notify the client that we are ready to go */ (* context->prepared_func) (context->pixbuf, NULL, context->user_data); - + } else if (!context->did_prescan) { + int rc; + + /* start decompression */ + cinfo->buffered_image = TRUE; + rc = jpeg_start_decompress (cinfo); + cinfo->do_fancy_upsampling = FALSE; + cinfo->do_block_smoothing = FALSE; + if (rc == JPEG_SUSPENDED) continue; diff --git a/gdk-pixbuf/io-png.c b/gdk-pixbuf/io-png.c index 9081096e7d..dc886f8322 100644 --- a/gdk-pixbuf/io-png.c +++ b/gdk-pixbuf/io-png.c @@ -386,7 +386,8 @@ struct _LoadContext { }; static gpointer -gdk_pixbuf__png_image_begin_load (ModulePreparedNotifyFunc prepare_func, +gdk_pixbuf__png_image_begin_load (ModuleSizeFunc size_func, + ModulePreparedNotifyFunc prepare_func, ModuleUpdatedNotifyFunc update_func, gpointer user_data, GError **error) diff --git a/gdk-pixbuf/io-pnm.c b/gdk-pixbuf/io-pnm.c index 797f937178..c137191464 100644 --- a/gdk-pixbuf/io-pnm.c +++ b/gdk-pixbuf/io-pnm.c @@ -81,7 +81,8 @@ typedef struct { } PnmLoaderContext; static GdkPixbuf *gdk_pixbuf__pnm_image_load (FILE *f, GError **error); -static gpointer gdk_pixbuf__pnm_image_begin_load (ModulePreparedNotifyFunc func, +static gpointer gdk_pixbuf__pnm_image_begin_load (ModuleSizeFunc size_func, + ModulePreparedNotifyFunc func, ModuleUpdatedNotifyFunc func2, gpointer user_data, GError **error); @@ -803,7 +804,8 @@ gdk_pixbuf__pnm_image_load (FILE *f, GError **error) */ static gpointer -gdk_pixbuf__pnm_image_begin_load (ModulePreparedNotifyFunc prepared_func, +gdk_pixbuf__pnm_image_begin_load (ModuleSizeFunc size_func, + ModulePreparedNotifyFunc prepared_func, ModuleUpdatedNotifyFunc updated_func, gpointer user_data, GError **error) diff --git a/gdk-pixbuf/io-ras.c b/gdk-pixbuf/io-ras.c index cc39e6a28e..32bc35abf9 100644 --- a/gdk-pixbuf/io-ras.c +++ b/gdk-pixbuf/io-ras.c @@ -94,7 +94,8 @@ struct ras_progressive_state { }; static gpointer -gdk_pixbuf__ras_image_begin_load(ModulePreparedNotifyFunc prepared_func, +gdk_pixbuf__ras_image_begin_load(ModuleSizeFunc size_func, + ModulePreparedNotifyFunc prepared_func, ModuleUpdatedNotifyFunc updated_func, gpointer user_data, GError **error); @@ -114,7 +115,7 @@ static GdkPixbuf *gdk_pixbuf__ras_image_load(FILE * f, GError **error) GdkPixbuf *pb; - State = gdk_pixbuf__ras_image_begin_load(NULL, NULL, NULL, error); + State = gdk_pixbuf__ras_image_begin_load(NULL, NULL, NULL, NULL, error); membuf = g_malloc(4096); @@ -251,7 +252,8 @@ static gboolean RAS2State(struct rasterfile *RAS, */ static gpointer -gdk_pixbuf__ras_image_begin_load(ModulePreparedNotifyFunc prepared_func, +gdk_pixbuf__ras_image_begin_load(ModuleSizeFunc size_func, + ModulePreparedNotifyFunc prepared_func, ModuleUpdatedNotifyFunc updated_func, gpointer user_data, GError **error) diff --git a/gdk-pixbuf/io-tga.c b/gdk-pixbuf/io-tga.c index 87a7ea659a..08259d8323 100644 --- a/gdk-pixbuf/io-tga.c +++ b/gdk-pixbuf/io-tga.c @@ -801,7 +801,8 @@ static gboolean try_preload(TGAContext *ctx, GError **err) return TRUE; } -static gpointer gdk_pixbuf__tga_begin_load(ModulePreparedNotifyFunc f1, +static gpointer gdk_pixbuf__tga_begin_load(ModuleSizeFunc f0, + ModulePreparedNotifyFunc f1, ModuleUpdatedNotifyFunc f2, gpointer udata, GError **err) { diff --git a/gdk-pixbuf/io-tiff.c b/gdk-pixbuf/io-tiff.c index deae12bd77..d376147648 100644 --- a/gdk-pixbuf/io-tiff.c +++ b/gdk-pixbuf/io-tiff.c @@ -361,7 +361,8 @@ gdk_pixbuf__tiff_image_load (FILE *f, GError **error) /* Progressive loader */ static gpointer -gdk_pixbuf__tiff_image_begin_load (ModulePreparedNotifyFunc prepare_func, +gdk_pixbuf__tiff_image_begin_load (ModuleSizeFunc size_func, + ModulePreparedNotifyFunc prepare_func, ModuleUpdatedNotifyFunc update_func, gpointer user_data, GError **error) diff --git a/gdk-pixbuf/io-wbmp.c b/gdk-pixbuf/io-wbmp.c index bfbfb4c36e..14bb115365 100644 --- a/gdk-pixbuf/io-wbmp.c +++ b/gdk-pixbuf/io-wbmp.c @@ -63,7 +63,8 @@ struct wbmp_progressive_state { }; static gpointer -gdk_pixbuf__wbmp_image_begin_load(ModulePreparedNotifyFunc prepared_func, +gdk_pixbuf__wbmp_image_begin_load(ModuleSizeFunc size_func, + ModulePreparedNotifyFunc prepared_func, ModuleUpdatedNotifyFunc updated_func, gpointer user_data, GError **error); @@ -85,7 +86,7 @@ static GdkPixbuf *gdk_pixbuf__wbmp_image_load(FILE * f, GError **error) GdkPixbuf *pb; - State = gdk_pixbuf__wbmp_image_begin_load(NULL, NULL, NULL, + State = gdk_pixbuf__wbmp_image_begin_load(NULL, NULL, NULL, NULL, error); if (State == NULL) @@ -116,7 +117,8 @@ static GdkPixbuf *gdk_pixbuf__wbmp_image_load(FILE * f, GError **error) */ static gpointer -gdk_pixbuf__wbmp_image_begin_load(ModulePreparedNotifyFunc prepared_func, +gdk_pixbuf__wbmp_image_begin_load(ModuleSizeFunc size_func, + ModulePreparedNotifyFunc prepared_func, ModuleUpdatedNotifyFunc updated_func, gpointer user_data, GError **error) diff --git a/gdk-pixbuf/io-xbm.c b/gdk-pixbuf/io-xbm.c index 3ef06bb2a8..71e6e40393 100644 --- a/gdk-pixbuf/io-xbm.c +++ b/gdk-pixbuf/io-xbm.c @@ -353,7 +353,8 @@ gdk_pixbuf__xbm_image_load (FILE *f, GError **error) */ static gpointer -gdk_pixbuf__xbm_image_begin_load (ModulePreparedNotifyFunc prepare_func, +gdk_pixbuf__xbm_image_begin_load (ModuleSizeFunc size_func, + ModulePreparedNotifyFunc prepare_func, ModuleUpdatedNotifyFunc update_func, gpointer user_data, GError **error) diff --git a/gdk-pixbuf/io-xpm.c b/gdk-pixbuf/io-xpm.c index 6f47766768..ee9d44e385 100644 --- a/gdk-pixbuf/io-xpm.c +++ b/gdk-pixbuf/io-xpm.c @@ -1416,7 +1416,8 @@ struct _XPMContext * in the future. */ static gpointer -gdk_pixbuf__xpm_image_begin_load (ModulePreparedNotifyFunc prepare_func, +gdk_pixbuf__xpm_image_begin_load (ModuleSizeFunc size_func, + ModulePreparedNotifyFunc prepare_func, ModuleUpdatedNotifyFunc update_func, gpointer user_data, GError **error) |