Exemplo n.º 1
0
static void
prepared_callback (GdkPixbufLoader *loader,
                   gpointer data)
{
    AniLoaderContext *context = (AniLoaderContext*)data;

#ifdef DEBUG_ANI
    g_print ("%d pixbuf prepared\n", context->pos);
#endif

    GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
    if (!pixbuf)
        return;

    if (gdk_pixbuf_get_width (pixbuf) > context->animation->width)
        context->animation->width = gdk_pixbuf_get_width (pixbuf);

    if (gdk_pixbuf_get_height (pixbuf) > context->animation->height)
        context->animation->height = gdk_pixbuf_get_height (pixbuf);

    if (context->title != NULL)
        gdk_pixbuf_set_option (pixbuf, "Title", context->title);

    if (context->author != NULL)
        gdk_pixbuf_set_option (pixbuf, "Author", context->author);

    g_object_ref (pixbuf);
    context->animation->pixbufs[context->pos] = pixbuf;

    if (context->pos == 0)
    {
        if (context->prepared_func)
            (* context->prepared_func) (pixbuf,
                                        GDK_PIXBUF_ANIMATION (context->animation),
                                        context->user_data);
    }
    else {
        /* FIXME - this is necessary for nice display of loading
           animations because GtkImage ignores
           gdk_pixbuf_animation_iter_on_currently_loading_frame()
           and always exposes the full frame */
        GdkPixbuf *last = context->animation->pixbufs[context->pos - 1];
        gint width = MIN (gdk_pixbuf_get_width (last), gdk_pixbuf_get_width (pixbuf));
        gint height = MIN (gdk_pixbuf_get_height (last), gdk_pixbuf_get_height (pixbuf));
        gdk_pixbuf_copy_area (last, 0, 0, width, height, pixbuf, 0, 0);
    }

    context->pos++;
}
Exemplo n.º 2
0
/**
 * gdk_cursor_get_image:
 * @cursor: a #GdkCursor
 *
 * Returns a #GdkPixbuf with the image used to display the cursor.
 *
 * Note that depending on the capabilities of the windowing system and 
 * on the cursor, GDK may not be able to obtain the image data. In this 
 * case, %NULL is returned.
 *
 * Returns: (transfer full): a #GdkPixbuf representing @cursor, or %NULL
 *
 * Since: 2.8
 */
GdkPixbuf*  
gdk_cursor_get_image (GdkCursor *cursor)
{
  int w, h;
  cairo_surface_t *surface;
  GdkPixbuf *pixbuf;
  gchar buf[32];
  double x_hot, y_hot;
  double x_scale, y_scale;

  g_return_val_if_fail (GDK_IS_CURSOR (cursor), NULL);

  surface = gdk_cursor_get_surface (cursor, &x_hot, &y_hot);
  if (surface == NULL)
    return NULL;

  w = cairo_image_surface_get_width (surface);
  h = cairo_image_surface_get_height (surface);

  x_scale = y_scale = 1;
#ifdef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE
  cairo_surface_get_device_scale (surface, &x_scale, &y_scale);
#endif

  pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0, w, h);
  cairo_surface_destroy (surface);

  if (x_scale != 1)
    {
      GdkPixbuf *old;

      old = pixbuf;
      pixbuf = gdk_pixbuf_scale_simple (old,
					w / x_scale, h / y_scale,
					GDK_INTERP_HYPER);
      g_object_unref (old);
    }

  
  g_snprintf (buf, 32, "%d", (int)x_hot);
  gdk_pixbuf_set_option (pixbuf, "x_hot", buf);

  g_snprintf (buf, 32, "%d", (int)y_hot);
  gdk_pixbuf_set_option (pixbuf, "y_hot", buf);

  return pixbuf;
}
Exemplo n.º 3
0
GdkPixbuf *
file_to_pixbuf (const char  *path,
		guint        destination_size,
	        GError     **error)
{
	GdkPixbuf *pixbuf, *tmp_pixbuf;
	GFile *file;
	char *uri;
	int original_width, original_height;

	file = g_file_new_for_path (path);
	uri = g_file_get_uri (file);
	pixbuf = _gdk_pixbuf_new_from_uri_at_scale (uri, destination_size, error);
	if (pixbuf == NULL)
		return NULL;

	tmp_pixbuf = gdk_pixbuf_apply_embedded_orientation (pixbuf);
	gdk_pixbuf_copy_options (pixbuf, tmp_pixbuf);
	gdk_pixbuf_remove_option (tmp_pixbuf, "orientation");
	g_object_unref (pixbuf);
	pixbuf = tmp_pixbuf;

        original_width = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (pixbuf),
                                                             "gnome-original-width"));
        original_height = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (pixbuf),
                                                              "gnome-original-height"));

	if (original_width > 0 && original_height > 0) {
		char *tmp;

		tmp = g_strdup_printf ("%d", original_width);
		gdk_pixbuf_set_option (pixbuf, "tEXt::Thumb::Image::Width", tmp);
		g_free (tmp);

		tmp = g_strdup_printf ("%d", original_height);
		gdk_pixbuf_set_option (pixbuf, "tEXt::Thumb::Image::Height", tmp);
		g_free (tmp);
	}

	return pixbuf;
}
Exemplo n.º 4
0
Arquivo: io-xpm.c Projeto: chipx86/gtk
/* This function does all the work. */
static GdkPixbuf *
pixbuf_create_from_xpm (const gchar * (*get_buf) (enum buf_op op, gpointer handle), gpointer handle,
                        GError **error)
{
	gint w, h, n_col, cpp, x_hot, y_hot, items;
	gint cnt, xcnt, ycnt, wbytes, n;
	gint is_trans = FALSE;
	const gchar *buffer;
        gchar *name_buf;
	gchar pixel_str[32];
	GHashTable *color_hash;
	XPMColor *colors, *color, *fallbackcolor;
	guchar *pixtmp;
	GdkPixbuf *pixbuf;

	fallbackcolor = NULL;

	buffer = (*get_buf) (op_header, handle);
	if (!buffer) {
                g_set_error_literal (error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
                                     _("No XPM header found"));
		return NULL;
	}
	items = sscanf (buffer, "%d %d %d %d %d %d", &w, &h, &n_col, &cpp, &x_hot, &y_hot);

	if (items != 4 && items != 6) {
		g_set_error_literal (error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
                                     _("Invalid XPM header"));
		return NULL;
	}

	if (w <= 0) {
                g_set_error_literal (error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
                                     _("XPM file has image width <= 0"));
		return NULL;

	}
	if (h <= 0) {
                g_set_error_literal (error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
                                     _("XPM file has image height <= 0"));
		return NULL;

	}
	if (cpp <= 0 || cpp >= 32) {
                g_set_error_literal (error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
                                     _("XPM has invalid number of chars per pixel"));
		return NULL;
	}
	if (n_col <= 0 || 
	    n_col >= G_MAXINT / (cpp + 1) || 
	    n_col >= G_MAXINT / sizeof (XPMColor)) {
                g_set_error_literal (error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
                                     _("XPM file has invalid number of colors"));
		return NULL;
	}

	/* The hash is used for fast lookups of color from chars */
	color_hash = g_hash_table_new (g_str_hash, g_str_equal);

	name_buf = g_try_malloc (n_col * (cpp + 1));
	if (!name_buf) {
		g_set_error_literal (error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
                                     _("Cannot allocate memory for loading XPM image"));
		g_hash_table_destroy (color_hash);
		return NULL;
	}
	colors = (XPMColor *) g_try_malloc (sizeof (XPMColor) * n_col);
	if (!colors) {
		g_set_error_literal (error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
                                     _("Cannot allocate memory for loading XPM image"));
		g_hash_table_destroy (color_hash);
		g_free (name_buf);
		return NULL;
	}

	for (cnt = 0; cnt < n_col; cnt++) {
		gchar *color_name;

		buffer = (*get_buf) (op_cmap, handle);
		if (!buffer) {
                        g_set_error_literal (error,
                                             GDK_PIXBUF_ERROR,
                                             GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
                                             _("Cannot read XPM colormap"));
			g_hash_table_destroy (color_hash);
			g_free (name_buf);
			g_free (colors);
			return NULL;
		}

		color = &colors[cnt];
		color->color_string = &name_buf[cnt * (cpp + 1)];
		strncpy (color->color_string, buffer, cpp);
		color->color_string[cpp] = 0;
		buffer += strlen (color->color_string);
		color->transparent = FALSE;

		color_name = xpm_extract_color (buffer);

		if ((color_name == NULL) || (g_ascii_strcasecmp (color_name, "None") == 0)
		    || (parse_color (color_name, color) == FALSE)) {
			color->transparent = TRUE;
			color->red = 0;
			color->green = 0;
			color->blue = 0;
			is_trans = TRUE;
		}

		g_free (color_name);
		g_hash_table_insert (color_hash, color->color_string, color);

		if (cnt == 0)
			fallbackcolor = color;
	}

	pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, is_trans, 8, w, h);

	if (!pixbuf) {
                g_set_error_literal (error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
                                     _("Cannot allocate memory for loading XPM image"));
		g_hash_table_destroy (color_hash);
		g_free (colors);
		g_free (name_buf);
		return NULL;
	}

	wbytes = w * cpp;

	for (ycnt = 0; ycnt < h; ycnt++) {
		pixtmp = pixbuf->pixels + ycnt * pixbuf->rowstride;

		buffer = (*get_buf) (op_body, handle);
		if ((!buffer) || (strlen (buffer) < wbytes))
			continue;

		for (n = 0, xcnt = 0; n < wbytes; n += cpp, xcnt++) {
			strncpy (pixel_str, &buffer[n], cpp);
			pixel_str[cpp] = 0;

			color = g_hash_table_lookup (color_hash, pixel_str);

			/* Bad XPM...punt */
			if (!color)
				color = fallbackcolor;

			*pixtmp++ = color->red >> 8;
			*pixtmp++ = color->green >> 8;
			*pixtmp++ = color->blue >> 8;

			if (is_trans && color->transparent)
				*pixtmp++ = 0;
			else if (is_trans)
				*pixtmp++ = 0xFF;
		}
	}

	g_hash_table_destroy (color_hash);
	g_free (colors);
	g_free (name_buf);

	if (items == 6) {
		gchar hot[10];
		g_snprintf (hot, 10, "%d", x_hot);
		gdk_pixbuf_set_option (pixbuf, "x_hot", hot);
		g_snprintf (hot, 10, "%d", y_hot);
		gdk_pixbuf_set_option (pixbuf, "y_hot", hot);

	}

	return pixbuf;
}
Exemplo n.º 5
0
static GdkPixbuf *
tiff_image_parse (TIFF *tiff, TiffContext *context, GError **error)
{
	guchar *pixels = NULL;
	gint width, height, rowstride, bytes;
	GdkPixbuf *pixbuf;
	guint16 bits_per_sample = 0;
	uint16 orientation = 0;
	uint16 transform = 0;
        uint16 codec;
        gchar *icc_profile_base64;
        const gchar *icc_profile;
        guint icc_profile_size;
        uint16 resolution_unit;
        gchar *density_str;
        gint retval;

        /* We're called with the lock held. */

	if (!TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width)) {
                g_set_error_literal (error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_FAILED,
                                     _("Could not get image width (bad TIFF file)"));
                return NULL;
        }
        
        if (!TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height)) {
                g_set_error_literal (error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_FAILED,
                                     _("Could not get image height (bad TIFF file)"));
                return NULL;
        }

        if (width <= 0 || height <= 0) {
                g_set_error_literal (error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
                                     _("Width or height of TIFF image is zero"));
                return NULL;                
        }
        
        rowstride = width * 4;
        if (rowstride / 4 != width) { /* overflow */
                g_set_error_literal (error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
                                     _("Dimensions of TIFF image too large"));
                return NULL;                
        }
        
        bytes = height * rowstride;
        if (bytes / rowstride != height) { /* overflow */
                g_set_error_literal (error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
                                     _("Dimensions of TIFF image too large"));
                return NULL;                
        }

	if (context && context->size_func) {
                gint w = width;
                gint h = height;
		(* context->size_func) (&w, &h, context->user_data);
                
		/* This is a signal that this function is being called
		   to support gdk_pixbuf_get_file_info, so we can stop
		   parsing the tiff file at this point. It is not an
		   error condition. */

                if (w == 0 || h == 0)
                    return NULL;
        }

        pixels = g_try_malloc (bytes);

        if (!pixels) {
                g_set_error_literal (error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
                                     _("Insufficient memory to open TIFF file"));
                return NULL;
        }

	pixbuf = gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, TRUE, 8, 
                                           width, height, rowstride,
                                           free_buffer, NULL);
        if (!pixbuf) {
                g_free (pixels);
                g_set_error_literal (error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
                                     _("Insufficient memory to open TIFF file"));
                return NULL;
        }

        /* Save the bits per sample as an option since pixbufs are
           expected to be always 8 bits per sample. */
        TIFFGetField (tiff, TIFFTAG_BITSPERSAMPLE, &bits_per_sample);
        if (bits_per_sample > 0) {
                gchar str[5];
                g_snprintf (str, sizeof (str), "%d", bits_per_sample);
                gdk_pixbuf_set_option (pixbuf, "bits-per-sample", str);
        }

	/* Set the "orientation" key associated with this image. libtiff 
	   orientation handling is odd, so further processing is required
	   by higher-level functions based on this tag. If the embedded
	   orientation tag is 1-4, libtiff flips/mirrors the image as
	   required, and no client processing is required - so we report 
	   no orientation. Orientations 5-8 require rotations which would 
	   swap the width and height of the image. libtiff does not do this. 
	   Instead it interprets orientations 5-8 the same as 1-4. 
	   See http://bugzilla.remotesensing.org/show_bug.cgi?id=1548.
	   To correct for this, the client must apply the transform normally
	   used for orientation 5 to both orientations 5 and 7, and apply
	   the transform normally used for orientation 7 for both
	   orientations 6 and 8. Then everythings works out OK! */
	
	TIFFGetField (tiff, TIFFTAG_ORIENTATION, &orientation);

	switch (orientation) {
		case 5:
		case 7:
			transform = 5;
			break;
		case 6:
		case 8:
			transform = 7;
			break;
		default:
			transform = 0;
			break;
	}

	if (transform > 0 ) {
		gchar str[5];
		g_snprintf (str, sizeof (str), "%d", transform);
		gdk_pixbuf_set_option (pixbuf, "orientation", str);
	}

        TIFFGetField (tiff, TIFFTAG_COMPRESSION, &codec);
        if (codec > 0) {
          gchar str[5];
          g_snprintf (str, sizeof (str), "%d", codec);
          gdk_pixbuf_set_option (pixbuf, "compression", str);
        }

        /* Extract embedded ICC profile */
        retval = TIFFGetField (tiff, TIFFTAG_ICCPROFILE, &icc_profile_size, &icc_profile);
        if (retval == 1) {
                icc_profile_base64 = g_base64_encode ((const guchar *) icc_profile, icc_profile_size);
                gdk_pixbuf_set_option (pixbuf, "icc-profile", icc_profile_base64);
                g_free (icc_profile_base64);
        }

        retval = TIFFGetField (tiff, TIFFTAG_RESOLUTIONUNIT, &resolution_unit);
        if (retval == 1) {
                float x_resolution = 0, y_resolution = 0;

                TIFFGetField (tiff, TIFFTAG_XRESOLUTION, &x_resolution);
                TIFFGetField (tiff, TIFFTAG_YRESOLUTION, &y_resolution);

                switch (resolution_unit) {
                case RESUNIT_INCH:
                        density_str = g_strdup_printf ("%d", (int) round (x_resolution));
                        gdk_pixbuf_set_option (pixbuf, "x-dpi", density_str);
                        g_free (density_str);
                        density_str = g_strdup_printf ("%d", (int) round (y_resolution));
                        gdk_pixbuf_set_option (pixbuf, "y-dpi", density_str);
                        g_free (density_str);
                        break;
                case RESUNIT_CENTIMETER:
                        density_str = g_strdup_printf ("%d", DPCM_TO_DPI (x_resolution));
                        gdk_pixbuf_set_option (pixbuf, "x-dpi", density_str);
                        g_free (density_str);
                        density_str = g_strdup_printf ("%d", DPCM_TO_DPI (y_resolution));
                        gdk_pixbuf_set_option (pixbuf, "y-dpi", density_str);
                        g_free (density_str);
                        break;
                }
        }

	if (context && context->prepare_func)
		(* context->prepare_func) (pixbuf, NULL, context->user_data);

	if (!TIFFReadRGBAImageOriented (tiff, width, height, (uint32 *)pixels, ORIENTATION_TOPLEFT, 1)) {
		g_set_error_literal (error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_FAILED,
                                     _("Failed to load RGB data from TIFF file"));
		g_object_unref (pixbuf);
		return NULL;
	}

	/* Flag multi-page documents, because this loader only handles the
	   first page. The client app may wish to warn the user. */
        if (TIFFReadDirectory (tiff))
                gdk_pixbuf_set_option (pixbuf, "multipage", "yes");

#if G_BYTE_ORDER == G_BIG_ENDIAN
	/* Turns out that the packing used by TIFFRGBAImage depends on 
         * the host byte order... 
         */ 
	while (pixels < pixbuf->pixels + bytes) {
		uint32 pixel = *(uint32 *)pixels;
		int r = TIFFGetR(pixel);
		int g = TIFFGetG(pixel);
		int b = TIFFGetB(pixel);
		int a = TIFFGetA(pixel);
		*pixels++ = r;
		*pixels++ = g;
		*pixels++ = b;
		*pixels++ = a;
	}
#endif

	if (context && context->update_func)
		(* context->update_func) (pixbuf, 0, 0, width, height, context->user_data);

        return pixbuf;
}
Exemplo n.º 6
0
/*
 * context - from image_begin_load
 * buf - new image data
 * size - length of new image data
 *
 * append image data onto inrecrementally built output image
 */
static gboolean
gdk_pixbuf__jpeg_image_load_increment (gpointer data,
                                       const guchar *buf, guint size,
                                       GError **error)
{
	JpegProgContext *context = (JpegProgContext *)data;
	struct           jpeg_decompress_struct *cinfo;
	my_src_ptr       src;
	guint            num_left, num_copy;
	guint            last_num_left, last_bytes_left;
	guint            spinguard;
	gboolean         first;
	const guchar    *bufhd;
	gint             width, height;
        int              is_otag;
	char             otag_str[5];

	g_return_val_if_fail (context != NULL, FALSE);
	g_return_val_if_fail (buf != NULL, FALSE);

	src = (my_src_ptr) context->cinfo.src;

	cinfo = &context->cinfo;

        context->jerr.error = error;
        
	/* check for fatal error */
	if (sigsetjmp (context->jerr.setjmp_buffer, 1)) {
		return FALSE;
	}

	/* skip over data if requested, handle unsigned int sizes cleanly */
	/* only can happen if we've already called jpeg_get_header once   */
	if (context->src_initialized && src->skip_next) {
		if (src->skip_next > size) {
			src->skip_next -= size;
			return TRUE;
		} else {
			num_left = size - src->skip_next;
			bufhd = buf + src->skip_next;
			src->skip_next = 0;
		}
	} else {
		num_left = size;
		bufhd = buf;
	}

	if (num_left == 0)
		return TRUE;

	last_num_left = num_left;
	last_bytes_left = 0;
	spinguard = 0;
	first = TRUE;
	while (TRUE) {

		/* handle any data from caller we haven't processed yet */
		if (num_left > 0) {
			if(src->pub.bytes_in_buffer && 
			   src->pub.next_input_byte != src->buffer)
				memmove(src->buffer, src->pub.next_input_byte,
					src->pub.bytes_in_buffer);


			num_copy = MIN (JPEG_PROG_BUF_SIZE - src->pub.bytes_in_buffer,
					num_left);

			memcpy(src->buffer + src->pub.bytes_in_buffer, bufhd,num_copy);
			src->pub.next_input_byte = src->buffer;
			src->pub.bytes_in_buffer += num_copy;
			bufhd += num_copy;
			num_left -= num_copy;
		}

                /* did anything change from last pass, if not return */
                if (first) {
                        last_bytes_left = src->pub.bytes_in_buffer;
                        first = FALSE;
                } else if (src->pub.bytes_in_buffer == last_bytes_left
			   && num_left == last_num_left) {
                        spinguard++;
		} else {
                        last_bytes_left = src->pub.bytes_in_buffer;
			last_num_left = num_left;
		}

		/* should not go through twice and not pull bytes out of buf */
		if (spinguard > 2)
			return TRUE;

		/* try to load jpeg header */
		if (!context->got_header) {
			int rc;
		
			jpeg_save_markers (cinfo, EXIF_JPEG_MARKER, 0xffff);
			rc = jpeg_read_header (cinfo, TRUE);
			context->src_initialized = TRUE;
			
			if (rc == JPEG_SUSPENDED)
				continue;
			
			context->got_header = TRUE;

			/* check for orientation tag */
			is_otag = get_orientation (cinfo);
		
			width = cinfo->image_width;
			height = cinfo->image_height;
			if (context->size_func) {
				(* context->size_func) (&width, &height, context->user_data);
				if (width == 0 || height == 0) {
					g_set_error_literal (error,
                                                             GDK_PIXBUF_ERROR,
                                                             GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
                                                             _("Transformed JPEG has zero width or height."));
					return FALSE;
				}
			}
			
			cinfo->scale_num = 1;
			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_literal (error,
                                                     GDK_PIXBUF_ERROR,
                                                     GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
                                                     _("Couldn't allocate memory for loading JPEG file"));
                                return FALSE;
			}
		
		        /* if orientation tag was found set an option to remember its value */
		        if (is_otag) {
                		g_snprintf (otag_str, sizeof (otag_str), "%d", is_otag);
		                gdk_pixbuf_set_option (context->pixbuf, "orientation", otag_str);
		        }

			/* Use pixbuf buffer to store decompressed data */
			context->dptr = context->pixbuf->pixels;
			
			/* Notify the client that we are ready to go */
			if (context->prepared_func)
				(* context->prepared_func) (context->pixbuf,
							    NULL,
							    context->user_data);
			
		} else if (!context->did_prescan) {
			int rc;			
			
			/* start decompression */
			cinfo->buffered_image = cinfo->progressive_mode;
			rc = jpeg_start_decompress (cinfo);
			cinfo->do_fancy_upsampling = FALSE;
			cinfo->do_block_smoothing = FALSE;

			if (rc == JPEG_SUSPENDED)
				continue;

			context->did_prescan = TRUE;
		} else if (!cinfo->buffered_image) {
                        /* we're decompressing unbuffered so
                         * simply get scanline by scanline from jpeg lib
                         */
                        if (! gdk_pixbuf__jpeg_image_load_lines (context,
                                                                 error))
                                return FALSE;

			if (cinfo->output_scanline >= cinfo->output_height)
				return TRUE;
		} else {
                        /* we're decompressing buffered (progressive)
                         * so feed jpeg lib scanlines
                         */

			/* keep going until we've done all passes */
			while (!jpeg_input_complete (cinfo)) {
				if (!context->in_output) {
					if (jpeg_start_output (cinfo, cinfo->input_scan_number)) {
						context->in_output = TRUE;
						context->dptr = context->pixbuf->pixels;
					}
					else
						break;
				}

                                /* get scanlines from jpeg lib */
                                if (! gdk_pixbuf__jpeg_image_load_lines (context,
                                                                         error))
                                        return FALSE;

				if (cinfo->output_scanline >= cinfo->output_height &&
				    jpeg_finish_output (cinfo))
					context->in_output = FALSE;
				else
					break;
			}
			if (jpeg_input_complete (cinfo))
				/* did entire image */
				return TRUE;
			else
				continue;
		}
	}
}
Exemplo n.º 7
0
/* Shared library entry point */
static GdkPixbuf *
gdk_pixbuf__jpeg_image_load (FILE *f, GError **error)
{
	gint   i;
	int     is_otag;
	char   otag_str[5];
	GdkPixbuf * volatile pixbuf = NULL;
	guchar *dptr;
	guchar *lines[4]; /* Used to expand rows, via rec_outbuf_height, 
                           * from the header file: 
                           * " Usually rec_outbuf_height will be 1 or 2, 
                           * at most 4."
			   */
	guchar **lptr;
	struct jpeg_decompress_struct cinfo;
	struct error_handler_data jerr;
	stdio_src_ptr src;

	/* setup error handler */
	cinfo.err = jpeg_std_error (&jerr.pub);
	jerr.pub.error_exit = fatal_error_handler;
        jerr.pub.output_message = output_message_handler;
        jerr.error = error;
        
	if (sigsetjmp (jerr.setjmp_buffer, 1)) {
		/* Whoops there was a jpeg error */
		if (pixbuf)
			g_object_unref (pixbuf);

		jpeg_destroy_decompress (&cinfo);

		/* error should have been set by fatal_error_handler () */
		return NULL;
	}

	/* load header, setup */
	jpeg_create_decompress (&cinfo);

	cinfo.src = (struct jpeg_source_mgr *)
	  (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
				  sizeof (stdio_source_mgr));
	src = (stdio_src_ptr) cinfo.src;
	src->buffer = (JOCTET *)
	  (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
				      JPEG_PROG_BUF_SIZE * sizeof (JOCTET));

	src->pub.init_source = stdio_init_source;
	src->pub.fill_input_buffer = stdio_fill_input_buffer;
	src->pub.skip_input_data = stdio_skip_input_data;
	src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
	src->pub.term_source = stdio_term_source;
	src->infile = f;
	src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
	src->pub.next_input_byte = NULL; /* until buffer loaded */

	jpeg_save_markers (&cinfo, EXIF_JPEG_MARKER, 0xffff);
	jpeg_read_header (&cinfo, TRUE);

	/* check for orientation tag */
	is_otag = get_orientation (&cinfo);
	
	jpeg_start_decompress (&cinfo);
	cinfo.do_fancy_upsampling = FALSE;
	cinfo.do_block_smoothing = FALSE;

	pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, 
				 cinfo.out_color_components == 4 ? TRUE : FALSE, 
				 8, cinfo.output_width, cinfo.output_height);
	      
	if (!pixbuf) {
		jpeg_destroy_decompress (&cinfo);

                /* broken check for *error == NULL for robustness against
                 * crappy JPEG library
                 */
                if (error && *error == NULL) {
                        g_set_error_literal (error,
                                             GDK_PIXBUF_ERROR,
                                             GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
                                             _("Insufficient memory to load image, try exiting some applications to free memory"));
                }
                
		return NULL;
	}

	/* if orientation tag was found set an option to remember its value */
	if (is_otag) {
		g_snprintf (otag_str, sizeof (otag_str), "%d", is_otag);
		gdk_pixbuf_set_option (pixbuf, "orientation", otag_str);
	}


	dptr = pixbuf->pixels;

	/* decompress all the lines, a few at a time */
	while (cinfo.output_scanline < cinfo.output_height) {
		lptr = lines;
		for (i = 0; i < cinfo.rec_outbuf_height; i++) {
			*lptr++ = dptr;
			dptr += pixbuf->rowstride;
		}

		jpeg_read_scanlines (&cinfo, lines, cinfo.rec_outbuf_height);

		switch (cinfo.out_color_space) {
		    case JCS_GRAYSCALE:
		      explode_gray_into_buf (&cinfo, lines);
		      break;
		    case JCS_RGB:
		      /* do nothing */
		      break;
		    case JCS_CMYK:
		      convert_cmyk_to_rgb (&cinfo, lines);
		      break;
		    default:
		      g_object_unref (pixbuf);
		      if (error && *error == NULL) {
                        g_set_error (error,
                                     GDK_PIXBUF_ERROR,
				     GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
				     _("Unsupported JPEG color space (%s)"),
				     colorspace_name (cinfo.out_color_space)); 
		      }
                
		      jpeg_destroy_decompress (&cinfo);
		      return NULL;
		}
	}

	jpeg_finish_decompress (&cinfo);
	jpeg_destroy_decompress (&cinfo);

	return pixbuf;
}
Exemplo n.º 8
0
static GdkPixbuf *
gdip_bitmap_to_pixbuf (GpBitmap *bitmap, GError **error)
{
  GdkPixbuf *pixbuf = NULL;
  guchar *cursor = NULL;
  gint rowstride;
  gboolean has_alpha = FALSE;
  gint n_channels = 0;
  gchar *option;

  guint width = 0, height = 0, x, y;

  gdip_bitmap_get_size (bitmap, &width, &height);
  gdip_bitmap_get_has_alpha (bitmap, &has_alpha);

  pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, has_alpha, 8, width, height);

  if (!pixbuf) {
    g_set_error_literal (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, _("Couldn't load bitmap"));
    return NULL;
  }

  rowstride = gdk_pixbuf_get_rowstride (pixbuf);
  cursor = gdk_pixbuf_get_pixels (pixbuf);
  n_channels = gdk_pixbuf_get_n_channels (pixbuf);

  for (y = 0; y < height; y++) {
    for (x = 0; x < width; x++) {
      ARGB pixel;
      GpStatus status;
      guchar *b = cursor + (y * rowstride + (x * n_channels));
      
      if (Ok != (status = GdipBitmapGetPixel (bitmap, x, y, &pixel))) {
        gdip_set_error_from_gpstatus (error, GDK_PIXBUF_ERROR_FAILED, status);
        g_object_unref (pixbuf);
        return NULL;
      }
      
      b[0] = (pixel & 0xff0000) >> 16;
      b[1] = (pixel & 0x00ff00) >> 8;
      b[2] = (pixel & 0x0000ff) >> 0;
      
      if (has_alpha)      
        b[3] = (pixel & 0xff000000) >> 24;
    }
  }

  if (gdip_bitmap_get_property_as_string (bitmap, PropertyTagOrientation, &option)) {
    gdk_pixbuf_set_option (pixbuf, "orientation", option);
    g_free (option);
  }

  if (gdip_bitmap_get_property_as_string (bitmap, PropertyTagArtist, &option)) {
    gdk_pixbuf_set_option (pixbuf, "Author", option);
    g_free (option);
  }

  if (gdip_bitmap_get_property_as_string (bitmap, PropertyTagImageTitle, &option)) {
    gdk_pixbuf_set_option (pixbuf, "Title", option);
    g_free (option);
  }

  return pixbuf;
}
Exemplo n.º 9
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;
}
Exemplo n.º 10
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;
}
Exemplo n.º 11
0
static gboolean set_image_text(GObject* image, const char* key, const char* val)
{
    return gdk_pixbuf_set_option(GDK_PIXBUF(image), key, val);
}
Exemplo n.º 12
0
void generate_thumbnails_with_gdk_pixbuf(ThumbnailTask* task)
{
    /* FIXME: only formats supported by GdkPixbuf should be handled this way. */
    GFile* gf = fm_path_to_gfile(task->fi->path);
    GFileInputStream* ins;
    GdkPixbuf* normal_pix = NULL;
    GdkPixbuf* large_pix = NULL;

    DEBUG("generate thumbnail for %s", task->fi->path->name);

    if( ins = g_file_read(gf, generator_cancellable, NULL) )
    {
        GdkPixbuf* ori_pix;
        gssize len;
        ori_pix = gdk_pixbuf_new_from_stream(G_INPUT_STREAM(ins), generator_cancellable, NULL);
        if(ori_pix) /* if the original image is successfully loaded */
        {
            const char* orientation_str = gdk_pixbuf_get_option(ori_pix, "orientation");
            int width = gdk_pixbuf_get_width(ori_pix);
            int height = gdk_pixbuf_get_height(ori_pix);
            gboolean need_save;

            if(task->flags & GENERATE_NORMAL)
            {
                /* don't create thumbnails for images which are too small */
                if(width <=128 && height <= 128)
                {
                    normal_pix = (GdkPixbuf*)g_object_ref(ori_pix);
                    need_save = FALSE;
                }
                else
                {
                    normal_pix = scale_pix(ori_pix, 128);
                    need_save = TRUE;
                }
                if(orientation_str)
                {
                    GdkPixbuf* rotated;
                    gdk_pixbuf_set_option(normal_pix, "orientation", orientation_str);
                    rotated = gdk_pixbuf_apply_embedded_orientation(normal_pix);
                    g_object_unref(normal_pix);
                    normal_pix = rotated;
                }
                if(need_save)
                    save_thumbnail_to_disk(task, normal_pix, task->normal_path);
            }

            if(task->flags & GENERATE_LARGE)
            {
                /* don't create thumbnails for images which are too small */
                if(width <=256 && height <= 256)
                {
                    large_pix = (GdkPixbuf*)g_object_ref(ori_pix);
                    need_save = FALSE;
                }
                else
                {
                    large_pix = scale_pix(ori_pix, 256);
                    need_save = TRUE;
                }
                if(orientation_str)
                {
                    GdkPixbuf* rotated;
                    gdk_pixbuf_set_option(large_pix, "orientation", orientation_str);
                    rotated = gdk_pixbuf_apply_embedded_orientation(large_pix);
                    g_object_unref(large_pix);
                    large_pix = rotated;
                }
                if(need_save)
                    save_thumbnail_to_disk(task, large_pix, task->large_path);
            }
            g_object_unref(ori_pix);
        }
        g_input_stream_close(G_INPUT_STREAM(ins), NULL, NULL);
    }

    G_LOCK(queue);
    thumbnail_task_finish(task, normal_pix, large_pix);
    cur_generating = NULL;
    G_UNLOCK(queue);

    if(normal_pix)
        g_object_unref(normal_pix);
    if(large_pix)
        g_object_unref(large_pix);

    g_object_unref(gf);
}