diff options
author | Matthias Clasen <maclas@gmx.de> | 2004-01-07 00:26:58 +0000 |
---|---|---|
committer | Matthias Clasen <matthiasc@src.gnome.org> | 2004-01-07 00:26:58 +0000 |
commit | 5b26e695a1fc70c99b58f2e9c4c922412fbd1a08 (patch) | |
tree | 2f5f563c13bfc6d7427311b48bfbb36dd60e78a9 /gdk-pixbuf | |
parent | 72b7abd535ba6aeb0c5911b6e6a19ec26f90ecf7 (diff) | |
download | gdk-pixbuf-5b26e695a1fc70c99b58f2e9c4c922412fbd1a08.tar.gz |
Make it possible to call gdk_pixbuf_loader_set_size (loader, 0, 0) by
Wed Jan 7 01:17:36 2004 Matthias Clasen <maclas@gmx.de>
* gdk-pixbuf-loader.c (gdk_pixbuf_loader_size_func):
* gdk-pixbuf-loader.c (gdk_pixbuf_loader_set_size):
* gdk-pixbuf-loader.c (gdk_pixbuf_loader_init): Make it possible
to call gdk_pixbuf_loader_set_size (loader, 0, 0) by changing
the initial values of priv->width/height to -1.
* io-tiff.c (tiff_image_parse):
* io-ras.c (RAS2State):
* io-pnm.c (gdk_pixbuf__pnm_image_load_increment):
* io-pcx.c (gdk_pixbuf__pcx_load_increment):
* io-jpeg.c (gdk_pixbuf__jpeg_image_load_increment):
* io-png.c (png_info_callback):
* io-ico.c (DecodeHeader):
* io-bmp.c (DecodeHeader): Call size_func once the size is known,
even if the module can't make use of the scaling information. If
size_func returns 0, don't allocate a pixbuf and return, if
necessary with an error.
* gdk-pixbuf.h:
* gdk-pixbuf-io.c (gdk_pixbuf_get_file_info): A new function
to determine the type and size of an image file without loading
it completely. (#53725)
Diffstat (limited to 'gdk-pixbuf')
-rw-r--r-- | gdk-pixbuf/ChangeLog | 25 | ||||
-rw-r--r-- | gdk-pixbuf/gdk-pixbuf-io.c | 87 | ||||
-rw-r--r-- | gdk-pixbuf/gdk-pixbuf-loader.c | 7 | ||||
-rw-r--r-- | gdk-pixbuf/gdk-pixbuf.h | 4 | ||||
-rw-r--r-- | gdk-pixbuf/io-bmp.c | 62 | ||||
-rw-r--r-- | gdk-pixbuf/io-ico.c | 18 | ||||
-rw-r--r-- | gdk-pixbuf/io-jpeg.c | 7 | ||||
-rw-r--r-- | gdk-pixbuf/io-pcx.c | 8 | ||||
-rw-r--r-- | gdk-pixbuf/io-png.c | 15 | ||||
-rw-r--r-- | gdk-pixbuf/io-pnm.c | 12 | ||||
-rw-r--r-- | gdk-pixbuf/io-ras.c | 11 | ||||
-rw-r--r-- | gdk-pixbuf/io-tga.c | 12 | ||||
-rw-r--r-- | gdk-pixbuf/io-tiff.c | 11 |
13 files changed, 250 insertions, 29 deletions
diff --git a/gdk-pixbuf/ChangeLog b/gdk-pixbuf/ChangeLog index f11a942d3..796b17833 100644 --- a/gdk-pixbuf/ChangeLog +++ b/gdk-pixbuf/ChangeLog @@ -1,3 +1,28 @@ +Wed Jan 7 01:17:36 2004 Matthias Clasen <maclas@gmx.de> + + * gdk-pixbuf-loader.c (gdk_pixbuf_loader_size_func): + * gdk-pixbuf-loader.c (gdk_pixbuf_loader_set_size): + * gdk-pixbuf-loader.c (gdk_pixbuf_loader_init): Make it possible + to call gdk_pixbuf_loader_set_size (loader, 0, 0) by changing + the initial values of priv->width/height to -1. + + * io-tiff.c (tiff_image_parse): + * io-ras.c (RAS2State): + * io-pnm.c (gdk_pixbuf__pnm_image_load_increment): + * io-pcx.c (gdk_pixbuf__pcx_load_increment): + * io-jpeg.c (gdk_pixbuf__jpeg_image_load_increment): + * io-png.c (png_info_callback): + * io-ico.c (DecodeHeader): + * io-bmp.c (DecodeHeader): Call size_func once the size is known, + even if the module can't make use of the scaling information. If + size_func returns 0, don't allocate a pixbuf and return, if + necessary with an error. + + * gdk-pixbuf.h: + * gdk-pixbuf-io.c (gdk_pixbuf_get_file_info): A new function + to determine the type and size of an image file without loading + it completely. (#53725) + Sun Jan 4 00:44:57 2004 Matthias Clasen <maclas@gmx.de> * gdk-pixbuf.c (gdk_pixbuf_class_init): Turn the pixbuf diff --git a/gdk-pixbuf/gdk-pixbuf-io.c b/gdk-pixbuf/gdk-pixbuf-io.c index dc96b44d2..dc5dc5143 100644 --- a/gdk-pixbuf/gdk-pixbuf-io.c +++ b/gdk-pixbuf/gdk-pixbuf-io.c @@ -910,6 +910,93 @@ gdk_pixbuf_new_from_file_at_size (const char *filename, return pixbuf; } +static void +info_cb (GdkPixbufLoader *loader, + int width, + int height, + gpointer data) +{ + struct { + GdkPixbufFormat *format; + int width; + int height; + } *info = data; + + g_return_if_fail (width > 0 && height > 0); + + info->format = gdk_pixbuf_loader_get_format (loader); + info->width = width; + info->height = height; + + gdk_pixbuf_loader_set_size (loader, 0, 0); +} + +/** + * gdk_pixbuf_get_file_info: + * @filename: The name of the file to identify. + * @width: Return location for the width of the image, or %NULL + * @height: Return location for the height of the image, or %NULL + * + * Parses an image file far enough to determine its format and size. + * + * Returns: A #GdkPixbufFormat describing the image format of the file + * or %NULL if the image format wasn't recognized. The return value + * is owned by GdkPixbuf and should not be freed. + * + * Since: 2.4 + **/ +GdkPixbufFormat * +gdk_pixbuf_get_file_info (const gchar *filename, + gint *width, + gint *height) +{ + GdkPixbufLoader *loader; + GError *temp = NULL; + guchar buffer [4096]; + int length; + FILE *f; + struct { + GdkPixbufFormat *format; + gint width; + gint height; + } info; + + g_return_val_if_fail (filename != NULL, NULL); + + f = fopen (filename, "rb"); + if (!f) + return NULL; + + loader = gdk_pixbuf_loader_new (); + + info.format = NULL; + info.width = -1; + info.height = -1; + + g_signal_connect (loader, "size-prepared", G_CALLBACK (info_cb), &info); + + while (!feof (f)) { + length = fread (buffer, 1, sizeof (buffer), f); + if (length > 0) { + if (!gdk_pixbuf_loader_write (loader, buffer, length, NULL)) + break; + } + if (info.format != NULL) + break; + } + + fclose (f); + gdk_pixbuf_loader_close (loader, NULL); + g_object_unref (G_OBJECT (loader)); + + if (width) + *width = info.width; + if (height) + *height = info.height; + + return info.format; +} + /** * gdk_pixbuf_new_from_xpm_data: * @data: Pointer to inline XPM data. diff --git a/gdk-pixbuf/gdk-pixbuf-loader.c b/gdk-pixbuf/gdk-pixbuf-loader.c index b4c135252..d980eea97 100644 --- a/gdk-pixbuf/gdk-pixbuf-loader.c +++ b/gdk-pixbuf/gdk-pixbuf-loader.c @@ -208,6 +208,9 @@ gdk_pixbuf_loader_init (GdkPixbufLoader *loader) GdkPixbufLoaderPrivate *priv; priv = g_new0 (GdkPixbufLoaderPrivate, 1); + priv->width = -1; + priv->height = -1; + loader->priv = priv; } @@ -253,7 +256,7 @@ gdk_pixbuf_loader_set_size (GdkPixbufLoader *loader, gint height) { GdkPixbufLoaderPrivate *priv = GDK_PIXBUF_LOADER (loader)->priv; - g_return_if_fail (width > 0 && height > 0); + g_return_if_fail (width >= 0 && height >= 0); if (!priv->size_fixed) { @@ -268,7 +271,7 @@ 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) + if (priv->width == -1 && priv->height == -1) { priv->width = *width; priv->height = *height; diff --git a/gdk-pixbuf/gdk-pixbuf.h b/gdk-pixbuf/gdk-pixbuf.h index 0f5728f33..234f88310 100644 --- a/gdk-pixbuf/gdk-pixbuf.h +++ b/gdk-pixbuf/gdk-pixbuf.h @@ -302,6 +302,10 @@ gchar **gdk_pixbuf_format_get_mime_types (GdkPixbufFormat *format); gchar **gdk_pixbuf_format_get_extensions (GdkPixbufFormat *format); gboolean gdk_pixbuf_format_is_writable (GdkPixbufFormat *format); +GdkPixbufFormat *gdk_pixbuf_get_file_info (const gchar *filename, + gint *width, + gint *height); + G_END_DECLS #include <gdk-pixbuf/gdk-pixbuf-loader.h> diff --git a/gdk-pixbuf/io-bmp.c b/gdk-pixbuf/io-bmp.c index f7f50df15..8212834e1 100644 --- a/gdk-pixbuf/io-bmp.c +++ b/gdk-pixbuf/io-bmp.c @@ -144,6 +144,7 @@ struct bmp_compression_state { /* Progressive loading */ struct bmp_progressive_state { + GdkPixbufModuleSizeFunc size_func; GdkPixbufModulePreparedFunc prepared_func; GdkPixbufModuleUpdatedFunc updated_func; gpointer user_data; @@ -319,41 +320,52 @@ static gboolean DecodeHeader(unsigned char *BFH, unsigned char *BIH, State->LineWidth = (State->LineWidth / 4) * 4 + 4; if (State->pixbuf == NULL) { + if (State->size_func) { + gint width = State->Header.width; + gint height = State->Header.height; + + (*State->size_func) (&width, &height, State->user_data); + if (width == 0 || height == 0) { + State->read_state = READ_STATE_DONE; + State->BufferSize = 0; + return TRUE; + } + } + if (State->Type == 32 || State->Compressed == BI_RLE4 || State->Compressed == BI_RLE8) State->pixbuf = - gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, - (gint) State->Header.width, - (gint) State->Header.height); + gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, + (gint) State->Header.width, + (gint) State->Header.height); else State->pixbuf = - gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, - (gint) State->Header.width, - (gint) State->Header.height); - - if (State->pixbuf == NULL) { - g_set_error (error, - GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, - _("Not enough memory to load bitmap image")); + gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, + (gint) State->Header.width, + (gint) State->Header.height); + + if (State->pixbuf == NULL) { + g_set_error (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, + _("Not enough memory to load bitmap image")); State->read_state = READ_STATE_ERROR; - return FALSE; - } - + return FALSE; + } + if (State->prepared_func != NULL) /* Notify the client that we are ready to go */ (*State->prepared_func) (State->pixbuf, NULL, State->user_data); - + + /* make all pixels initially transparent */ + if (State->Compressed == BI_RLE4 || State->Compressed == BI_RLE8) { + memset (State->pixbuf->pixels, 0, State->pixbuf->rowstride * State->Header.height); + State->compr.p = State->pixbuf->pixels + + State->pixbuf->rowstride * (State->Header.height- 1); + } } - /* make all pixels initially transparent */ - if (State->Compressed == BI_RLE4 || State->Compressed == BI_RLE8) { - memset (State->pixbuf->pixels, 0, State->pixbuf->rowstride * State->Header.height); - State->compr.p = State->pixbuf->pixels - + State->pixbuf->rowstride * (State->Header.height- 1); - } - State->BufferDone = 0; if (State->Type <= 8) { State->read_state = READ_STATE_PALETTE; @@ -485,6 +497,7 @@ gdk_pixbuf__bmp_image_begin_load(GdkPixbufModuleSizeFunc size_func, struct bmp_progressive_state *context; context = g_new0(struct bmp_progressive_state, 1); + context->size_func = size_func; context->prepared_func = prepared_func; context->updated_func = updated_func; context->user_data = user_data; @@ -1036,6 +1049,9 @@ gdk_pixbuf__bmp_image_load_increment(gpointer data, return FALSE; break; + case READ_STATE_DONE: + return TRUE; + break; default: g_assert_not_reached (); diff --git a/gdk-pixbuf/io-ico.c b/gdk-pixbuf/io-ico.c index 482cff29a..e19f86f8f 100644 --- a/gdk-pixbuf/io-ico.c +++ b/gdk-pixbuf/io-ico.c @@ -126,6 +126,7 @@ struct headerpair { }; struct ico_progressive_state { + GdkPixbufModuleSizeFunc size_func; GdkPixbufModulePreparedFunc prepared_func; GdkPixbufModuleUpdatedFunc updated_func; gpointer user_data; @@ -400,6 +401,19 @@ static void DecodeHeader(guchar *Data, gint Bytes, if (State->pixbuf == NULL) { +#if 1 + if (State->size_func) { + gint width = State->Header.width; + gint height = State->Header.height; + + (*State->size_func) (&width, &height, State->user_data); + if (width == 0 || height == 0) { + State->LineWidth = 0; + return; + } + } +#endif + State->pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, State->Header.width, @@ -445,6 +459,7 @@ gdk_pixbuf__ico_image_begin_load(GdkPixbufModuleSizeFunc size_func, struct ico_progressive_state *context; context = g_new0(struct ico_progressive_state, 1); + context->size_func = size_func; context->prepared_func = prepared_func; context->updated_func = updated_func; context->user_data = user_data; @@ -828,6 +843,9 @@ gdk_pixbuf__ico_image_load_increment(gpointer data, GError *decode_err = NULL; DecodeHeader(context->HeaderBuf, context->HeaderDone, context, &decode_err); + if (context->LineBuf != NULL && context->LineWidth == 0) + return TRUE; + if (decode_err) { g_propagate_error (error, decode_err); return FALSE; diff --git a/gdk-pixbuf/io-jpeg.c b/gdk-pixbuf/io-jpeg.c index 191372890..85d75dfe6 100644 --- a/gdk-pixbuf/io-jpeg.c +++ b/gdk-pixbuf/io-jpeg.c @@ -650,7 +650,12 @@ gdk_pixbuf__jpeg_image_load_increment (gpointer data, width = cinfo->image_width; height = cinfo->image_height; - (* context->size_func) (&width, &height, context->user_data); + if (context->size_func) { + (* context->size_func) (&width, &height, context->user_data); + if (width == 0 || height == 0) + return FALSE; + } + 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) { diff --git a/gdk-pixbuf/io-pcx.c b/gdk-pixbuf/io-pcx.c index 5ccbeea5a..4a9d0bef8 100644 --- a/gdk-pixbuf/io-pcx.c +++ b/gdk-pixbuf/io-pcx.c @@ -606,8 +606,12 @@ gdk_pixbuf__pcx_load_increment(gpointer data, const guchar *buf, guint size, g_set_error(error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_CORRUPT_IMAGE, _("Image has invalid width and/or height")); return FALSE; } - if(context->size_func) - context->size_func(&width, &height, context->user_data); + if (context->size_func) + { + (*context->size_func) (&width, &height, context->user_data); + if (width == 0 || height == 0) + return TRUE; + } switch(context->bpp) { default: diff --git a/gdk-pixbuf/io-png.c b/gdk-pixbuf/io-png.c index 5ddca7510..fa35734a7 100644 --- a/gdk-pixbuf/io-png.c +++ b/gdk-pixbuf/io-png.c @@ -358,6 +358,7 @@ struct _LoadContext { png_structp png_read_ptr; png_infop png_info_ptr; + GdkPixbufModuleSizeFunc size_func; GdkPixbufModulePreparedFunc prepare_func; GdkPixbufModuleUpdatedFunc update_func; gpointer notify_user_data; @@ -398,6 +399,7 @@ gdk_pixbuf__png_image_begin_load (GdkPixbufModuleSizeFunc size_func, lc->fatal_error_occurred = FALSE; + lc->size_func = size_func; lc->prepare_func = prepare_func; lc->update_func = update_func; lc->notify_user_data = user_data; @@ -593,7 +595,18 @@ png_info_callback (png_structp png_read_ptr, if (color_type & PNG_COLOR_MASK_ALPHA) have_alpha = TRUE; - lc->pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, have_alpha, 8, width, height); + if (lc->size_func) { + gint w = width; + gint h = height; + (* lc->size_func) (&w, &h, lc->notify_user_data); + + if (w == 0 || h == 0) { + lc->fatal_error_occurred = TRUE; + return; + } + } + + lc->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, have_alpha, 8, width, height); if (lc->pixbuf == NULL) { /* Failed to allocate memory */ diff --git a/gdk-pixbuf/io-pnm.c b/gdk-pixbuf/io-pnm.c index 1fc1fe7c0..437ccaf0e 100644 --- a/gdk-pixbuf/io-pnm.c +++ b/gdk-pixbuf/io-pnm.c @@ -55,6 +55,7 @@ typedef struct { typedef struct { GdkPixbufModuleUpdatedFunc updated_func; GdkPixbufModulePreparedFunc prepared_func; + GdkPixbufModuleSizeFunc size_func; gpointer user_data; GdkPixbuf *pixbuf; @@ -820,6 +821,7 @@ gdk_pixbuf__pnm_image_begin_load (GdkPixbufModuleSizeFunc size_func, return NULL; } memset (context, 0, sizeof (PnmLoaderContext)); + context->size_func = size_func; context->prepared_func = prepared_func; context->updated_func = updated_func; context->user_data = user_data; @@ -944,6 +946,16 @@ gdk_pixbuf__pnm_image_load_increment (gpointer data, context->got_header = TRUE; } + + if (context->size_func) { + gint w = context->width; + gint h = context->height; + (*context->size_func) (&w, &h, context->user_data); + + if (w == 0 || h == 0) + return FALSE; + } + /* scan until we hit image data */ if (!context->did_prescan) { diff --git a/gdk-pixbuf/io-ras.c b/gdk-pixbuf/io-ras.c index fba4b9900..40ba370d5 100644 --- a/gdk-pixbuf/io-ras.c +++ b/gdk-pixbuf/io-ras.c @@ -68,6 +68,7 @@ struct rasterfile { /* Progressive loading */ struct ras_progressive_state { + GdkPixbufModuleSizeFunc size_func; GdkPixbufModulePreparedFunc prepared_func; GdkPixbufModuleUpdatedFunc updated_func; gpointer user_data; @@ -174,6 +175,15 @@ static gboolean RAS2State(struct rasterfile *RAS, if (!State->pixbuf) { + if (State->size_func) { + gint width = State->Header.width; + gint height = State->Header.height; + + (*State->size_func) (&width, &height, State->user_data); + if (width == 0 || height == 0) + return FALSE; + } + if (State->RasType == 32) State->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, (gint) State->Header.width, @@ -227,6 +237,7 @@ gdk_pixbuf__ras_image_begin_load(GdkPixbufModuleSizeFunc size_func, struct ras_progressive_state *context; context = g_new0(struct ras_progressive_state, 1); + context->size_func = size_func; context->prepared_func = prepared_func; context->updated_func = updated_func; context->user_data = user_data; diff --git a/gdk-pixbuf/io-tga.c b/gdk-pixbuf/io-tga.c index 1486d4480..32c6af0b5 100644 --- a/gdk-pixbuf/io-tga.c +++ b/gdk-pixbuf/io-tga.c @@ -137,6 +137,7 @@ struct _TGAContext { gboolean prepared; gboolean done; + GdkPixbufModuleSizeFunc sfunc; GdkPixbufModulePreparedFunc pfunc; GdkPixbufModuleUpdatedFunc ufunc; gpointer udata; @@ -334,6 +335,16 @@ static gboolean fill_in_context(TGAContext *ctx, GError **err) w = LE16(ctx->hdr->width); h = LE16(ctx->hdr->height); + if (ctx->sfunc) { + gint wi = w; + gint hi = h; + + (*ctx->sfunc) (&wi, &hi, ctx->udata); + + if (wi == 0 || hi == 0) + return FALSE; + } + ctx->pbuf = get_contiguous_pixbuf (w, h, alpha); if (!ctx->pbuf) { @@ -872,6 +883,7 @@ static gpointer gdk_pixbuf__tga_begin_load(GdkPixbufModuleSizeFunc f0, ctx->prepared = FALSE; ctx->done = FALSE; + ctx->sfunc = f0; ctx->pfunc = f1; ctx->ufunc = f2; ctx->udata = udata; diff --git a/gdk-pixbuf/io-tiff.c b/gdk-pixbuf/io-tiff.c index 3e6d9fca0..2d47f6594 100644 --- a/gdk-pixbuf/io-tiff.c +++ b/gdk-pixbuf/io-tiff.c @@ -47,6 +47,7 @@ typedef struct _TiffContext TiffContext; struct _TiffContext { + GdkPixbufModuleSizeFunc size_func; GdkPixbufModulePreparedFunc prepare_func; GdkPixbufModuleUpdatedFunc update_func; gpointer user_data; @@ -225,6 +226,15 @@ tiff_image_parse (TIFF *tiff, TiffContext *context, GError **error) return NULL; } + if (context && context->size_func) { + gint w = width; + gint h = height; + (* context->size_func) (&w, &h, context->user_data); + + if (w == 0 || h == 0) + return NULL; + } + pixels = g_try_malloc (bytes); if (!pixels) { @@ -370,6 +380,7 @@ gdk_pixbuf__tiff_image_begin_load (GdkPixbufModuleSizeFunc size_func, TiffContext *context; context = g_new0 (TiffContext, 1); + context->size_func = size_func; context->prepare_func = prepare_func; context->update_func = update_func; context->user_data = user_data; |