summaryrefslogtreecommitdiff
path: root/gdk-pixbuf
diff options
context:
space:
mode:
authorMatthias Clasen <maclas@gmx.de>2004-01-07 00:26:58 +0000
committerMatthias Clasen <matthiasc@src.gnome.org>2004-01-07 00:26:58 +0000
commit5b26e695a1fc70c99b58f2e9c4c922412fbd1a08 (patch)
tree2f5f563c13bfc6d7427311b48bfbb36dd60e78a9 /gdk-pixbuf
parent72b7abd535ba6aeb0c5911b6e6a19ec26f90ecf7 (diff)
downloadgdk-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/ChangeLog25
-rw-r--r--gdk-pixbuf/gdk-pixbuf-io.c87
-rw-r--r--gdk-pixbuf/gdk-pixbuf-loader.c7
-rw-r--r--gdk-pixbuf/gdk-pixbuf.h4
-rw-r--r--gdk-pixbuf/io-bmp.c62
-rw-r--r--gdk-pixbuf/io-ico.c18
-rw-r--r--gdk-pixbuf/io-jpeg.c7
-rw-r--r--gdk-pixbuf/io-pcx.c8
-rw-r--r--gdk-pixbuf/io-png.c15
-rw-r--r--gdk-pixbuf/io-pnm.c12
-rw-r--r--gdk-pixbuf/io-ras.c11
-rw-r--r--gdk-pixbuf/io-tga.c12
-rw-r--r--gdk-pixbuf/io-tiff.c11
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;