/** * 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; }
/** * 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; }
/** * 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; }