diff options
author | Richard Hughes <richard@hughsie.com> | 2016-01-21 19:02:03 +0000 |
---|---|---|
committer | Richard Hughes <richard@hughsie.com> | 2016-01-21 19:02:03 +0000 |
commit | 69e4f135a7332221b32096beaba063d5de072b67 (patch) | |
tree | 229c72df34cb68a94f56119b7cb9b862955067f7 | |
parent | 3460ddc196fafcaa1bb0f973c8db62462545c877 (diff) | |
download | appstream-glib-69e4f135a7332221b32096beaba063d5de072b67.tar.gz |
Add as_image_load_filename_full()
This makes it possible to resize icons from libappstream-glib
-rw-r--r-- | libappstream-builder/plugins/asb-plugin-desktop.c | 105 | ||||
-rw-r--r-- | libappstream-glib/as-image.c | 176 | ||||
-rw-r--r-- | libappstream-glib/as-image.h | 24 |
3 files changed, 188 insertions, 117 deletions
diff --git a/libappstream-builder/plugins/asb-plugin-desktop.c b/libappstream-builder/plugins/asb-plugin-desktop.c index 0af900a..ff0382d 100644 --- a/libappstream-builder/plugins/asb-plugin-desktop.c +++ b/libappstream-builder/plugins/asb-plugin-desktop.c @@ -63,105 +63,24 @@ asb_app_load_icon (AsbApp *app, guint min_icon_size, GError **error) { - GdkPixbuf *pixbuf = NULL; - guint pixbuf_height; - guint pixbuf_width; - guint tmp_height; - guint tmp_width; - g_autoptr(GdkPixbuf) pixbuf_src = NULL; - g_autoptr(GdkPixbuf) pixbuf_tmp = NULL; + g_autoptr(AsImage) im = NULL; + g_autoptr(GError) error_local = 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) { + im = as_image_new (); + if (!as_image_load_filename_full (im, + filename, + icon_size, + min_icon_size, + AS_IMAGE_LOAD_FLAG_NONE, + &error_local)) { 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)); + "%s: %s", + error_local->message, logfn); 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) { - g_autofree 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; + return g_object_ref (as_image_get_pixbuf (im)); } /** diff --git a/libappstream-glib/as-image.c b/libappstream-glib/as-image.c index bc008e6..10e1032 100644 --- a/libappstream-glib/as-image.c +++ b/libappstream-glib/as-image.c @@ -472,52 +472,180 @@ as_image_node_parse_dep11 (AsImage *im, GNode *node, } /** - * as_image_load_filename: + * 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 a pixbuf from a file. - * - * NOTE: This function also sets the suggested filename which can be retrieved - * using as_image_get_basename(). This can be overridden if required. + * Reads an image from a file. * * Returns: %TRUE for success * - * Since: 0.1.6 + * Since: 0.5.6 **/ gboolean -as_image_load_filename (AsImage *image, - const gchar *filename, - GError **error) +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); - gsize len; - g_autofree gchar *basename = NULL; - g_autofree gchar *data = NULL; + 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; - /* 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)) + /* 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; + + /* 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; + g_free (priv->md5); + priv->md5 = g_compute_checksum_for_data (G_CHECKSUM_MD5, + (guchar * )data, len); + } + + /* 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, + dest_size, + dest_size, + TRUE, error); + } else { + pixbuf_src = gdk_pixbuf_new_from_file (filename, error); + } + if (pixbuf_src == NULL) return FALSE; - g_free (priv->md5); - priv->md5 = g_compute_checksum_for_data (G_CHECKSUM_MD5, - (guchar * )data, len); - /* load the image */ - pixbuf = gdk_pixbuf_new_from_file (filename, error); - if (pixbuf == NULL) + /* 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 = gdk_pixbuf_get_width (pixbuf_src); + pixbuf_height = gdk_pixbuf_get_height (pixbuf_src); + if (pixbuf_width == dest_size && pixbuf_height == dest_size) { + as_image_set_pixbuf (image, pixbuf_src); + return TRUE; + } - /* set */ - basename = g_path_get_basename (filename); - as_image_set_basename (image, basename); + /* never scale up, just pad */ + if (pixbuf_width < dest_size && pixbuf_height < dest_size) { + g_debug ("icon padded to %ix%i as size %ix%i", + dest_size, dest_size, + pixbuf_width, pixbuf_height); + pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, + dest_size, dest_size); + gdk_pixbuf_fill (pixbuf, 0x00000000); + gdk_pixbuf_copy_area (pixbuf_src, + 0, 0, /* of src */ + pixbuf_width, pixbuf_height, + pixbuf, + (dest_size - pixbuf_width) / 2, + (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, + dest_size, 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, + dest_size, 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, tmp_width, 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 */ + tmp_width, tmp_height, + pixbuf, + (dest_size - tmp_width) / 2, + (dest_size - tmp_height) / 2); as_image_set_pixbuf (image, pixbuf); return TRUE; } /** + * as_image_load_filename: + * @image: a #AsImage instance. + * @filename: filename to read from + * @error: A #GError or %NULL. + * + * Reads a pixbuf from a file. + * + * NOTE: This function also sets the suggested filename which can be retrieved + * using as_image_get_basename(). This can be overridden if required. + * + * Returns: %TRUE for success + * + * Since: 0.1.6 + **/ +gboolean +as_image_load_filename (AsImage *image, + const gchar *filename, + GError **error) +{ + return as_image_load_filename_full (image, + filename, + 0, 0, + AS_IMAGE_LOAD_FLAG_SET_BASENAME | + AS_IMAGE_LOAD_FLAG_SET_CHECKSUM, + error); +} + +/** * as_image_save_pixbuf: * @image: a #AsImage instance. * @width: target width, or 0 for default diff --git a/libappstream-glib/as-image.h b/libappstream-glib/as-image.h index 03e7bb5..fb5fa07 100644 --- a/libappstream-glib/as-image.h +++ b/libappstream-glib/as-image.h @@ -83,6 +83,24 @@ typedef enum { } AsImageSaveFlags; /** + * AsImageLoadFlags: + * @AS_IMAGE_LOAD_FLAG_NONE: No special flags set + * @AS_IMAGE_LOAD_FLAG_SHARPEN: Sharpen the resulting image + * @AS_IMAGE_LOAD_FLAG_SET_BASENAME: Set the image basename + * @AS_IMAGE_LOAD_FLAG_SET_CHECKSUM: Set the image checksum + * + * The flags used for loading images. + **/ +typedef enum { + AS_IMAGE_LOAD_FLAG_NONE = 0, /* Since: 0.5.6 */ + AS_IMAGE_LOAD_FLAG_SHARPEN = 1, /* Since: 0.5.6 */ + AS_IMAGE_LOAD_FLAG_SET_BASENAME = 2, /* Since: 0.5.6 */ + AS_IMAGE_LOAD_FLAG_SET_CHECKSUM = 4, /* Since: 0.5.6 */ + /*< private >*/ + AS_IMAGE_LOAD_FLAG_LAST +} AsImageLoadFlags; + +/** * AsImageAlphaFlags: * @AS_IMAGE_ALPHA_FLAG_NONE: No padding detected * @AS_IMAGE_ALPHA_FLAG_TOP: Padding detected at the image top @@ -146,6 +164,12 @@ AsImageAlphaFlags as_image_get_alpha_flags (AsImage *image); gboolean as_image_load_filename (AsImage *image, const gchar *filename, GError **error); +gboolean as_image_load_filename_full (AsImage *image, + const gchar *filename, + guint dest_size, + guint src_size_min, + AsImageLoadFlags flags, + GError **error); GdkPixbuf *as_image_save_pixbuf (AsImage *image, guint width, guint height, |