Ejemplo n.º 1
0
/* Shared library entry point */
static GdkPixbuf *
gdk_pixbuf__png_image_load (FILE *f, GError **error)
{
        GdkPixbuf * volatile pixbuf = NULL;
	png_structp png_ptr;
	png_infop info_ptr;
        png_textp text_ptr;
	gint i, ctype;
	png_uint_32 w, h;
	png_bytepp volatile rows = NULL;
        gint    num_texts;
        gchar *key;
        gchar *value;
        gchar *icc_profile_base64;
        const gchar *icc_profile_title;
        const gchar *icc_profile;
        png_uint_32 icc_profile_size;
        guint32 retval;
        gint compression_type;

#ifdef PNG_USER_MEM_SUPPORTED
	png_ptr = png_create_read_struct_2 (PNG_LIBPNG_VER_STRING,
                                            error,
                                            png_simple_error_callback,
                                            png_simple_warning_callback,
                                            NULL, 
                                            png_malloc_callback, 
                                            png_free_callback);
#else
	png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,
                                          error,
                                          png_simple_error_callback,
                                          png_simple_warning_callback);
#endif
	if (!png_ptr)
		return NULL;

	info_ptr = png_create_info_struct (png_ptr);
	if (!info_ptr) {
		png_destroy_read_struct (&png_ptr, NULL, NULL);
		return NULL;
	}

	if (setjmp (png_jmpbuf(png_ptr))) {
	    	g_free (rows);

		if (pixbuf)
			g_object_unref (pixbuf);

		png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
		return NULL;
	}

	png_init_io (png_ptr, f);
	png_read_info (png_ptr, info_ptr);

        if (!setup_png_transformations(png_ptr, info_ptr, error, &w, &h, &ctype)) {
                png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
                return NULL;
        }
        
        pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, ctype & PNG_COLOR_MASK_ALPHA, 8, w, h);

	if (!pixbuf) {
                if (error && *error == NULL) {
                        g_set_error_literal (error,
                                             GDK_PIXBUF_ERROR,
                                             GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
                                             _("Insufficient memory to load PNG file"));
                }
                

		png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
		return NULL;
	}

	rows = g_new (png_bytep, h);

	for (i = 0; i < h; i++)
		rows[i] = pixbuf->pixels + i * pixbuf->rowstride;

	png_read_image (png_ptr, rows);
        png_read_end (png_ptr, info_ptr);

        if (png_get_text (png_ptr, info_ptr, &text_ptr, &num_texts)) {
                for (i = 0; i < num_texts; i++) {
                        png_text_to_pixbuf_option (text_ptr[i], &key, &value);
                        gdk_pixbuf_set_option (pixbuf, key, value);
                        g_free (key);
                        g_free (value);
                }
        }

#if defined(PNG_cHRM_SUPPORTED)
        /* Extract embedded ICC profile */
        retval = png_get_iCCP (png_ptr, info_ptr,
                               (png_charpp) &icc_profile_title, &compression_type,
                               (png_bytepp) &icc_profile, (png_uint_32*) &icc_profile_size);
        if (retval != 0) {
                icc_profile_base64 = g_base64_encode ((const guchar *) icc_profile, (gsize)icc_profile_size);
                gdk_pixbuf_set_option (pixbuf, "icc-profile", icc_profile_base64);
                g_free (icc_profile_base64);
        }
#endif

	g_free (rows);
	png_destroy_read_struct (&png_ptr, &info_ptr, NULL);

        return pixbuf;
}
Ejemplo n.º 2
0
/* Called at the start of the progressive load, once we have image info */
static void
png_info_callback   (png_structp png_read_ptr,
                     png_infop   png_info_ptr)
{
        LoadContext* lc;
        png_uint_32 width, height;
        png_textp png_text_ptr;
        int i, num_texts;
        int color_type;
        gboolean have_alpha = FALSE;
        gchar *icc_profile_base64;
        const gchar *icc_profile_title;
        const gchar *icc_profile;
        png_uint_32 icc_profile_size;
        guint32 retval;
        gint compression_type;

        lc = png_get_progressive_ptr(png_read_ptr);

        if (lc->fatal_error_occurred)
                return;

        if (!setup_png_transformations(lc->png_read_ptr,
                                       lc->png_info_ptr,
                                       lc->error,
                                       &width, &height, &color_type)) {
                lc->fatal_error_occurred = TRUE;
                return;
        }

        /* If we have alpha, set a flag */
        if (color_type & PNG_COLOR_MASK_ALPHA)
                have_alpha = TRUE;
        
        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;
                        if (lc->error && *lc->error == NULL) {
                                g_set_error_literal (lc->error,
                                                     GDK_PIXBUF_ERROR,
                                                     GDK_PIXBUF_ERROR_FAILED,
                                                     _("Transformed PNG has zero width or height."));
                        }
                        return;
                }
        }

        lc->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, have_alpha, 8, width, height);

        if (lc->pixbuf == NULL) {
                /* Failed to allocate memory */
                lc->fatal_error_occurred = TRUE;
                if (lc->error && *lc->error == NULL) {
                        g_set_error (lc->error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
                                     _("Insufficient memory to store a %lu by %lu image; try exiting some applications to reduce memory usage"),
                                     (gulong) width, (gulong) height);
                }
                return;
        }

        /* Extract text chunks and attach them as pixbuf options */
        
        if (png_get_text (png_read_ptr, png_info_ptr, &png_text_ptr, &num_texts)) {
                for (i = 0; i < num_texts; i++) {
                        gchar *key, *value;

                        if (png_text_to_pixbuf_option (png_text_ptr[i],
                                                       &key, &value)) {
                                gdk_pixbuf_set_option (lc->pixbuf, key, value);
                                g_free (key);
                                g_free (value);
                        }
                }
        }

#if defined(PNG_cHRM_SUPPORTED)
        /* Extract embedded ICC profile */
        retval = png_get_iCCP (png_read_ptr, png_info_ptr,
                               (png_charpp) &icc_profile_title, &compression_type,
                               (png_bytepp) &icc_profile, &icc_profile_size);
        if (retval != 0) {
                icc_profile_base64 = g_base64_encode ((const guchar *) icc_profile, (gsize)icc_profile_size);
                gdk_pixbuf_set_option (lc->pixbuf, "icc-profile", icc_profile_base64);
                g_free (icc_profile_base64);
        }
#endif

        /* Notify the client that we are ready to go */

        if (lc->prepare_func)
                (* lc->prepare_func) (lc->pixbuf, NULL, lc->notify_user_data);

        return;
}
Ejemplo n.º 3
0
static char *
get_real_name_from_nautilus_cache (const char *cache_path)
{
	FILE          *f;
	char          *result;
	png_structp    png_ptr = NULL;
	png_infop      info_ptr = NULL;
	png_textp      text_ptr = NULL;
	int            num_texts;

	cache_path = get_file_path_from_uri (cache_path);
	if (cache_path == NULL)
		return NULL;

	f = fopen (cache_path, "r");

	if (f == NULL)
		return NULL;

	png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,
					  NULL,
					  png_simple_error_callback,
					  png_simple_warning_callback);

        if (png_ptr == NULL) {
		fclose (f);
		return NULL;
	}

	info_ptr = png_create_info_struct (png_ptr);
	if (info_ptr == NULL) {
		png_destroy_read_struct (&png_ptr, NULL, NULL);
		fclose (f);
		return NULL;
	}

	if (setjmp (png_ptr->jmpbuf)) {
		png_destroy_read_struct (&png_ptr, NULL, NULL);
		fclose (f);
		return NULL;
	}

	result = NULL;
	png_init_io (png_ptr, f);
	png_read_info (png_ptr, info_ptr);

	if (png_get_text (png_ptr, info_ptr, &text_ptr, &num_texts)) {
		int    i;
		char  *key;
		char  *value;

		for (i = 0; i < num_texts; i++) {
			png_text_to_pixbuf_option (text_ptr[i], &key, &value);
			if ((key != NULL)
			    && (strcmp (key, "tEXt::Thumb::URI") == 0)
			    && (value != NULL)) {
				int ofs = 0;
				if (strncmp (value, "file://", 7) == 0)
					ofs = 7;
				result = g_strdup (value + ofs);
			}
                        g_free (key);
			g_free (value);
		}
	}

	png_destroy_read_struct (&png_ptr, &info_ptr, NULL);

	fclose (f);

	return result;
}