Exemplo n.º 1
0
/**
 * as_image_save_pixbuf:
 * @image: a #AsImage instance.
 * @width: target width, or 0 for default
 * @height: target height, or 0 for default
 * @flags: some #AsImageSaveFlags values, e.g. %AS_IMAGE_SAVE_FLAG_PAD_16_9
 *
 * Resamples a pixbuf to a specific size.
 *
 * Returns: (transfer full): A #GdkPixbuf of the specified size
 *
 * Since: 0.1.6
 **/
GdkPixbuf *
as_image_save_pixbuf (AsImage *image,
		      guint width,
		      guint height,
		      AsImageSaveFlags flags)
{
	AsImagePrivate *priv = GET_PRIVATE (image);
	GdkPixbuf *pixbuf = NULL;
	guint tmp_height;
	guint tmp_width;
	guint pixbuf_height;
	guint pixbuf_width;
	g_autoptr(GdkPixbuf) pixbuf_tmp = NULL;

	/* never set */
	if (priv->pixbuf == NULL)
		return NULL;

	/* 0 means 'default' */
	if (width == 0)
		width = gdk_pixbuf_get_width (priv->pixbuf);
	if (height == 0)
		height = gdk_pixbuf_get_height (priv->pixbuf);

	/* don't do anything to an image with the correct size */
	pixbuf_width = gdk_pixbuf_get_width (priv->pixbuf);
	pixbuf_height = gdk_pixbuf_get_height (priv->pixbuf);
	if (width == pixbuf_width && height == pixbuf_height)
		return g_object_ref (priv->pixbuf);

	/* is the aspect ratio of the source perfectly 16:9 */
	if (flags == AS_IMAGE_SAVE_FLAG_NONE ||
	    (pixbuf_width / 16) * 9 == pixbuf_height) {
		pixbuf = gdk_pixbuf_scale_simple (priv->pixbuf,
						  width, height,
						  GDK_INTERP_HYPER);
		if ((flags & AS_IMAGE_SAVE_FLAG_SHARPEN) > 0)
			as_pixbuf_sharpen (pixbuf, 1, -0.5);
		if ((flags & AS_IMAGE_SAVE_FLAG_BLUR) > 0)
			as_pixbuf_blur (pixbuf, 5, 3);
		return pixbuf;
	}

	/* create new 16:9 pixbuf with alpha padding */
	pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
				 TRUE, 8,
				 width,
				 height);
	gdk_pixbuf_fill (pixbuf, 0x00000000);
	if ((pixbuf_width / 16) * 9 > pixbuf_height) {
		tmp_width = width;
		tmp_height = width * pixbuf_height / pixbuf_width;
	} else {
		tmp_width = height * pixbuf_width / pixbuf_height;
		tmp_height = height;
	}
	pixbuf_tmp = gdk_pixbuf_scale_simple (priv->pixbuf,
					      tmp_width, tmp_height,
					      GDK_INTERP_HYPER);
	if ((flags & AS_IMAGE_SAVE_FLAG_SHARPEN) > 0)
		as_pixbuf_sharpen (pixbuf_tmp, 1, -0.5);
	if ((flags & AS_IMAGE_SAVE_FLAG_BLUR) > 0)
		as_pixbuf_blur (pixbuf_tmp, 5, 3);
	gdk_pixbuf_copy_area (pixbuf_tmp,
			      0, 0, /* of src */
			      tmp_width, tmp_height,
			      pixbuf,
			      (width - tmp_width) / 2,
			      (height - tmp_height) / 2);
	return pixbuf;
}
Exemplo n.º 2
0
/**
 * asb_app_load_icon:
 */
static GdkPixbuf *
asb_app_load_icon (AsbApp *app,
		   const gchar *filename,
		   const gchar *logfn,
		   guint icon_size,
		   guint min_icon_size,
		   GError **error)
{
	GdkPixbuf *pixbuf = NULL;
	guint pixbuf_height;
	guint pixbuf_width;
	guint tmp_height;
	guint tmp_width;
	_cleanup_object_unref_ GdkPixbuf *pixbuf_src = NULL;
	_cleanup_object_unref_ GdkPixbuf *pixbuf_tmp = NULL;

	/* open file in native size */
	if (g_str_has_suffix (filename, ".svg")) {
		pixbuf_src = gdk_pixbuf_new_from_file_at_scale (filename,
								icon_size,
								icon_size,
								TRUE, error);
	} else {
		pixbuf_src = gdk_pixbuf_new_from_file (filename, error);
	}
	if (pixbuf_src == NULL)
		return NULL;

	/* check size */
	if (gdk_pixbuf_get_width (pixbuf_src) < (gint) min_icon_size &&
	    gdk_pixbuf_get_height (pixbuf_src) < (gint) min_icon_size) {
		g_set_error (error,
			     ASB_PLUGIN_ERROR,
			     ASB_PLUGIN_ERROR_FAILED,
			     "icon %s was too small %ix%i",
			     logfn,
			     gdk_pixbuf_get_width (pixbuf_src),
			     gdk_pixbuf_get_height (pixbuf_src));
		return NULL;
	}

	/* does the icon not have an alpha channel */
	if (!gdk_pixbuf_get_has_alpha (pixbuf_src)) {
		asb_package_log (asb_app_get_package (app),
				 ASB_PACKAGE_LOG_LEVEL_INFO,
				 "icon %s does not have an alpha channel",
				 logfn);
	}

	/* don't do anything to an icon with the perfect size */
	pixbuf_width = gdk_pixbuf_get_width (pixbuf_src);
	pixbuf_height = gdk_pixbuf_get_height (pixbuf_src);
	if (pixbuf_width == icon_size && pixbuf_height == icon_size)
		return g_object_ref (pixbuf_src);

	/* never scale up, just pad */
	if (pixbuf_width < icon_size && pixbuf_height < icon_size) {
		_cleanup_free_ gchar *size_str = NULL;
		size_str = g_strdup_printf ("%ix%i",
					    pixbuf_width,
					    pixbuf_height);
		asb_package_log (asb_app_get_package (app),
				 ASB_PACKAGE_LOG_LEVEL_INFO,
				 "icon %s padded to %ix%i as size %s",
				 logfn, icon_size, icon_size, size_str);
		pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
					 icon_size, icon_size);
		gdk_pixbuf_fill (pixbuf, 0x00000000);
		gdk_pixbuf_copy_area (pixbuf_src,
				      0, 0, /* of src */
				      pixbuf_width, pixbuf_height,
				      pixbuf,
				      (icon_size - pixbuf_width) / 2,
				      (icon_size - pixbuf_height) / 2);
		return pixbuf;
	}

	/* is the aspect ratio perfectly square */
	if (pixbuf_width == pixbuf_height) {
		pixbuf = gdk_pixbuf_scale_simple (pixbuf_src,
						  icon_size, icon_size,
						  GDK_INTERP_HYPER);
		as_pixbuf_sharpen (pixbuf, 1, -0.5);
		return pixbuf;
	}

	/* create new square pixbuf with alpha padding */
	pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
				 icon_size, icon_size);
	gdk_pixbuf_fill (pixbuf, 0x00000000);
	if (pixbuf_width > pixbuf_height) {
		tmp_width = icon_size;
		tmp_height = icon_size * pixbuf_height / pixbuf_width;
	} else {
		tmp_width = icon_size * pixbuf_width / pixbuf_height;
		tmp_height = icon_size;
	}
	pixbuf_tmp = gdk_pixbuf_scale_simple (pixbuf_src, tmp_width, tmp_height,
					      GDK_INTERP_HYPER);
	as_pixbuf_sharpen (pixbuf_tmp, 1, -0.5);
	gdk_pixbuf_copy_area (pixbuf_tmp,
			      0, 0, /* of src */
			      tmp_width, tmp_height,
			      pixbuf,
			      (icon_size - tmp_width) / 2,
			      (icon_size - tmp_height) / 2);
	return pixbuf;
}
Exemplo n.º 3
0
/**
 * as_image_load_filename_full:
 * @image: a #AsImage instance.
 * @filename: filename to read from
 * @dest_size: The size of the constructed pixbuf, or 0 for the native size
 * @src_size_min: The smallest source size allowed, or 0 for none
 * @flags: a #AsImageLoadFlags, e.g. %AS_IMAGE_LOAD_FLAG_NONE
 * @error: A #GError or %NULL.
 *
 * Reads an image from a file.
 *
 * Returns: %TRUE for success
 *
 * Since: 0.5.6
 **/
gboolean
as_image_load_filename_full (AsImage *image,
			     const gchar *filename,
			     guint dest_size,
			     guint src_size_min,
			     AsImageLoadFlags flags,
			     GError **error)
{
	AsImagePrivate *priv = GET_PRIVATE (image);
	guint pixbuf_height;
	guint pixbuf_width;
	guint tmp_height;
	guint tmp_width;
	g_autoptr(GdkPixbuf) pixbuf = NULL;
	g_autoptr(GdkPixbuf) pixbuf_src = NULL;
	g_autoptr(GdkPixbuf) pixbuf_tmp = NULL;

	/* only support non-deprecated types */
	if (flags & AS_IMAGE_LOAD_FLAG_ONLY_SUPPORTED) {
		GdkPixbufFormat *fmt;
		fmt = gdk_pixbuf_get_file_info (filename, NULL, NULL);
		if (fmt == NULL) {
			g_set_error_literal (error,
					     AS_UTILS_ERROR,
					     AS_UTILS_ERROR_FAILED,
					     "image format was not recognized");
			return FALSE;
		}
		if (g_strcmp0 (gdk_pixbuf_format_get_name (fmt), "png") != 0 &&
		    g_strcmp0 (gdk_pixbuf_format_get_name (fmt), "jpeg") != 0 &&
		    g_strcmp0 (gdk_pixbuf_format_get_name (fmt), "xpm") != 0 &&
		    g_strcmp0 (gdk_pixbuf_format_get_name (fmt), "svg") != 0) {
			g_set_error (error,
				     AS_UTILS_ERROR,
				     AS_UTILS_ERROR_FAILED,
				     "image format %s is not supported",
				     gdk_pixbuf_format_get_name (fmt));
			return FALSE;
		}
	}

	/* update basename */
	if (flags & AS_IMAGE_LOAD_FLAG_SET_BASENAME) {
		g_autofree gchar *basename = NULL;
		basename = g_path_get_basename (filename);
		as_image_set_basename (image, basename);
	}

	/* update checksum */
	if (flags & AS_IMAGE_LOAD_FLAG_SET_CHECKSUM) {
		gsize len;
		g_autofree gchar *data = NULL;
		g_autofree gchar *md5_tmp = NULL;

		/* get the contents so we can hash the predictable file data,
		 * rather than the unpredicatable (for JPEG) pixel data */
		if (!g_file_get_contents (filename, &data, &len, error))
			return FALSE;
		md5_tmp = g_compute_checksum_for_data (G_CHECKSUM_MD5,
						       (guchar * )data, len);
		as_ref_string_assign_safe (&priv->md5, md5_tmp);
	}

	/* load the image of the native size */
	if (dest_size == 0) {
		pixbuf = gdk_pixbuf_new_from_file (filename, error);
		if (pixbuf == NULL)
			return FALSE;
		as_image_set_pixbuf (image, pixbuf);
		return TRUE;
	}

	/* open file in native size */
	if (g_str_has_suffix (filename, ".svg")) {
		pixbuf_src = gdk_pixbuf_new_from_file_at_scale (filename,
								(gint) dest_size,
								(gint) dest_size,
								TRUE, error);
	} else {
		pixbuf_src = gdk_pixbuf_new_from_file (filename, error);
	}
	if (pixbuf_src == NULL)
		return FALSE;

	/* check size */
	if (gdk_pixbuf_get_width (pixbuf_src) < (gint) src_size_min &&
	    gdk_pixbuf_get_height (pixbuf_src) < (gint) src_size_min) {
		g_set_error (error,
			     AS_UTILS_ERROR,
			     AS_UTILS_ERROR_FAILED,
			     "icon was too small %ix%i",
			     gdk_pixbuf_get_width (pixbuf_src),
			     gdk_pixbuf_get_height (pixbuf_src));
		return FALSE;
	}

	/* don't do anything to an icon with the perfect size */
	pixbuf_width = (guint) gdk_pixbuf_get_width (pixbuf_src);
	pixbuf_height = (guint) gdk_pixbuf_get_height (pixbuf_src);
	if (pixbuf_width == dest_size && pixbuf_height == dest_size) {
		as_image_set_pixbuf (image, pixbuf_src);
		return TRUE;
	}

	/* never scale up, just pad */
	if (pixbuf_width < dest_size && pixbuf_height < dest_size) {
		g_debug ("icon padded to %ux%u as size %ux%u",
			 dest_size, dest_size,
			 pixbuf_width, pixbuf_height);
		pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
					 (gint) dest_size, (gint) dest_size);
		gdk_pixbuf_fill (pixbuf, 0x00000000);
		gdk_pixbuf_copy_area (pixbuf_src,
				      0, 0, /* of src */
				      (gint) pixbuf_width,
				      (gint) pixbuf_height,
				      pixbuf,
				      (gint) (dest_size - pixbuf_width) / 2,
				      (gint) (dest_size - pixbuf_height) / 2);
		as_image_set_pixbuf (image, pixbuf);
		return TRUE;
	}

	/* is the aspect ratio perfectly square */
	if (pixbuf_width == pixbuf_height) {
		pixbuf = gdk_pixbuf_scale_simple (pixbuf_src,
						  (gint) dest_size,
						  (gint) dest_size,
						  GDK_INTERP_HYPER);
		as_image_set_pixbuf (image, pixbuf);
		return TRUE;
	}

	/* create new square pixbuf with alpha padding */
	pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
				 (gint) dest_size, (gint) dest_size);
	gdk_pixbuf_fill (pixbuf, 0x00000000);
	if (pixbuf_width > pixbuf_height) {
		tmp_width = dest_size;
		tmp_height = dest_size * pixbuf_height / pixbuf_width;
	} else {
		tmp_width = dest_size * pixbuf_width / pixbuf_height;
		tmp_height = dest_size;
	}
	pixbuf_tmp = gdk_pixbuf_scale_simple (pixbuf_src,
					      (gint) tmp_width,
					      (gint) tmp_height,
					      GDK_INTERP_HYPER);
	if (flags & AS_IMAGE_LOAD_FLAG_SHARPEN)
		as_pixbuf_sharpen (pixbuf_tmp, 1, -0.5);
	gdk_pixbuf_copy_area (pixbuf_tmp,
			      0, 0, /* of src */
			      (gint) tmp_width, (gint) tmp_height,
			      pixbuf,
			      (gint) (dest_size - tmp_width) / 2,
			      (gint) (dest_size - tmp_height) / 2);
	as_image_set_pixbuf (image, pixbuf);
	return TRUE;
}