Restructured to use gdk_pixbuf_new instead of manually allocating image

* io-png.c (gdk_pixbuf__png_image_load): Restructured to use
	gdk_pixbuf_new instead of manually allocating image storage. This
	gives us a good rowstride and overflow checks.  (#77807)
This commit is contained in:
Matthias Clasen 2002-04-06 18:51:40 +00:00
parent a40561930a
commit 71e0ad8d9e
2 changed files with 22 additions and 51 deletions

View File

@ -1,3 +1,9 @@
2002-04-06 Matthias Clasen <maclas@gmx.de>
* io-png.c (gdk_pixbuf__png_image_load): Restructured to use
gdk_pixbuf_new instead of manually allocating image storage. This
gives us a good rowstride and overflow checks. (#77807)
2002-04-05 Matthias Clasen <maclas@gmx.de> 2002-04-05 Matthias Clasen <maclas@gmx.de>
* io-tiff.c (tiff_image_parse): Avoid allocating an extra copy of * io-tiff.c (tiff_image_parse): Avoid allocating an extra copy of

View File

@ -199,13 +199,6 @@ png_simple_warning_callback(png_structp png_save_ptr,
*/ */
} }
/* Destroy notification function for the pixbuf */
static void
free_buffer (guchar *pixels, gpointer data)
{
g_free (pixels);
}
static gboolean static gboolean
png_text_to_pixbuf_option (png_text text_ptr, png_text_to_pixbuf_option (png_text text_ptr,
gchar **key, gchar **key,
@ -240,16 +233,16 @@ png_free_callback (png_structp o, png_voidp x)
static GdkPixbuf * static GdkPixbuf *
gdk_pixbuf__png_image_load (FILE *f, GError **error) gdk_pixbuf__png_image_load (FILE *f, GError **error)
{ {
GdkPixbuf *pixbuf; GdkPixbuf * volatile pixbuf = NULL;
png_structp png_ptr; png_structp png_ptr;
png_infop info_ptr; png_infop info_ptr;
png_textp text_ptr; png_textp text_ptr;
gint i, ctype, bpp; gint i, ctype;
png_uint_32 w, h; png_uint_32 w, h;
png_bytepp volatile rows = NULL; png_bytepp volatile rows = NULL;
guchar * volatile pixels = NULL;
gint num_texts; gint num_texts;
gchar **options = NULL; gchar *key;
gchar *value;
#ifdef PNG_USER_MEM_SUPPORTED #ifdef PNG_USER_MEM_SUPPORTED
png_ptr = png_create_read_struct_2 (PNG_LIBPNG_VER_STRING, png_ptr = png_create_read_struct_2 (PNG_LIBPNG_VER_STRING,
@ -278,8 +271,8 @@ gdk_pixbuf__png_image_load (FILE *f, GError **error)
if (rows) if (rows)
g_free (rows); g_free (rows);
if (pixels) if (pixbuf)
g_free (pixels); g_object_unref (pixbuf);
png_destroy_read_struct (&png_ptr, &info_ptr, NULL); png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
return NULL; return NULL;
@ -293,16 +286,9 @@ gdk_pixbuf__png_image_load (FILE *f, GError **error)
return NULL; return NULL;
} }
if (ctype & PNG_COLOR_MASK_ALPHA) pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, ctype & PNG_COLOR_MASK_ALPHA, 8, w, h);
bpp = 4;
else
bpp = 3;
pixels = g_try_malloc (w * h * bpp); if (!pixbuf) {
if (!pixels) {
/* Check error NULL, normally this would be broken,
* but libpng makes me want to code defensively.
*/
if (error && *error == NULL) { if (error && *error == NULL) {
g_set_error (error, g_set_error (error,
GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR,
@ -310,6 +296,7 @@ gdk_pixbuf__png_image_load (FILE *f, GError **error)
_("Insufficient memory to load PNG file")); _("Insufficient memory to load PNG file"));
} }
png_destroy_read_struct (&png_ptr, &info_ptr, NULL); png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
return NULL; return NULL;
} }
@ -317,44 +304,22 @@ gdk_pixbuf__png_image_load (FILE *f, GError **error)
rows = g_new (png_bytep, h); rows = g_new (png_bytep, h);
for (i = 0; i < h; i++) for (i = 0; i < h; i++)
rows[i] = pixels + i * w * bpp; rows[i] = pixbuf->pixels + i * pixbuf->rowstride;
png_read_image (png_ptr, rows); png_read_image (png_ptr, rows);
png_read_end (png_ptr, info_ptr); png_read_end (png_ptr, info_ptr);
if (png_get_text (png_ptr, info_ptr, &text_ptr, &num_texts)) { if (png_get_text (png_ptr, info_ptr, &text_ptr, &num_texts)) {
options = g_new (gchar *, num_texts * 2);
for (i = 0; i < num_texts; i++) { for (i = 0; i < num_texts; i++) {
png_text_to_pixbuf_option (text_ptr[i], png_text_to_pixbuf_option (text_ptr[i], &key, &value);
options + 2*i, gdk_pixbuf_set_option (pixbuf, key, value);
options + 2*i + 1); g_free (key);
g_free (value);
} }
} }
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
g_free (rows); g_free (rows);
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
if (ctype & PNG_COLOR_MASK_ALPHA)
pixbuf = gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, TRUE, 8,
w, h, w * 4,
free_buffer, NULL);
else
pixbuf = gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, FALSE, 8,
w, h, w * 3,
free_buffer, NULL);
if (options) {
for (i = 0; i < num_texts; i++) {
if (pixbuf) {
if (!gdk_pixbuf_set_option (pixbuf,
options[2*i],
options[2*i+1]))
g_warning ("Got multiple tEXt chunks for the same key.");
}
g_free (options[2*i]);
g_free (options[2*i+1]);
}
g_free (options);
}
return pixbuf; return pixbuf;
} }