aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXavier Claessens <xclaesse@gmail.com>2010-05-20 22:12:57 +0800
committerXavier Claessens <xclaesse@gmail.com>2010-06-01 16:34:21 +0800
commit039a533b0df07962485d1f433cb100cfbe76de05 (patch)
treef0a0f78b549bfd49da21f6aea2515aa0b27da6e6
parent371e91b25039b8dc1ac2489f9ef5dd5aa21cab7a (diff)
downloadgsoc2013-empathy-039a533b0df07962485d1f433cb100cfbe76de05.tar
gsoc2013-empathy-039a533b0df07962485d1f433cb100cfbe76de05.tar.gz
gsoc2013-empathy-039a533b0df07962485d1f433cb100cfbe76de05.tar.bz2
gsoc2013-empathy-039a533b0df07962485d1f433cb100cfbe76de05.tar.lz
gsoc2013-empathy-039a533b0df07962485d1f433cb100cfbe76de05.tar.xz
gsoc2013-empathy-039a533b0df07962485d1f433cb100cfbe76de05.tar.zst
gsoc2013-empathy-039a533b0df07962485d1f433cb100cfbe76de05.zip
Make sure to not infinite loop when scaling avatar.
1) Add a limit of 10 retries, to be sure to never do more in the worst case. 2) Only keep converted data that respect the requirements, make sure to not accept bigger data than maximum_bytes, even if it is close to the limit. 3) Stop the loop if the new factor does not change the image resolution. That means we already found the optimal size. Fixes bug #619701
-rw-r--r--libempathy-gtk/empathy-avatar-chooser.c55
1 files changed, 37 insertions, 18 deletions
diff --git a/libempathy-gtk/empathy-avatar-chooser.c b/libempathy-gtk/empathy-avatar-chooser.c
index bd2f4097b..c1dfbbdcf 100644
--- a/libempathy-gtk/empathy-avatar-chooser.c
+++ b/libempathy-gtk/empathy-avatar-chooser.c
@@ -417,8 +417,9 @@ avatar_chooser_maybe_convert_and_scale (EmpathyAvatarChooser *chooser,
gchar *new_mime_type = NULL;
gdouble min_factor, max_factor;
gdouble factor;
- gchar *converted_image_data = NULL;
- gsize converted_image_size = 0;
+ gchar *best_image_data = NULL;
+ gsize best_image_size = 0;
+ guint count = 0;
g_object_get (priv->factory,
"avatar-mime-types", &mime_types, /* Needs g_strfreev-ing */
@@ -492,10 +493,10 @@ avatar_chooser_maybe_convert_and_scale (EmpathyAvatarChooser *chooser,
GdkPixbuf *pixbuf_scaled = NULL;
gboolean saved;
gint new_width, new_height;
+ gchar *converted_image_data;
+ gsize converted_image_size;
GError *error = NULL;
- g_free (converted_image_data);
-
if (factor != 1) {
new_width = width * factor;
new_height = height * factor;
@@ -532,8 +533,23 @@ avatar_chooser_maybe_convert_and_scale (EmpathyAvatarChooser *chooser,
DEBUG ("Produced an image data of %"G_GSIZE_FORMAT" bytes.",
converted_image_size);
- if (max_size == 0)
- break;
+ /* If the new image satisfy the req, keep it as current best */
+ if (max_size == 0 ||
+ converted_image_size <= max_size) {
+ if (best_image_data)
+ g_free (best_image_data);
+
+ best_image_data = converted_image_data;
+ best_image_size = converted_image_size;
+
+ /* If this image is close enough to the optimal size,
+ * stop searching */
+ if (max_size == 0 ||
+ max_size - converted_image_size <= 1024)
+ break;
+ } else {
+ g_free (converted_image_data);
+ }
/* Make a binary search for the bigest factor that produce
* an image data size less than max_size */
@@ -543,20 +559,23 @@ avatar_chooser_maybe_convert_and_scale (EmpathyAvatarChooser *chooser,
min_factor = factor;
factor = (min_factor + max_factor)/2;
- /* We are done if either:
- * - min_factor == max_factor. That happens if we resized to
- * the max required dimension and the produced data size is
- * less than max_size.
- * - The data size is close enough to max_size. Here we accept
- * a difference of 1k.
- */
- } while (min_factor != max_factor &&
- abs (max_size - converted_image_size) > 1024);
+ if ((int) (width * factor) == new_width ||
+ (int) (height * factor) == new_height) {
+ /* min_factor and max_factor are too close, so the new
+ * factor will produce the same image as previous
+ * iteration. No need to continue, we already found
+ * the optimal size. */
+ break;
+ }
+
+ /* Do 10 iterations in the worst case */
+ } while (++count < 10);
+
g_free (new_format_name);
- /* Takes ownership of new_mime_type and converted_image_data */
- avatar = empathy_avatar_new ((guchar *) converted_image_data,
- converted_image_size, new_mime_type, NULL, NULL);
+ /* Takes ownership of new_mime_type and best_image_data */
+ avatar = empathy_avatar_new ((guchar *) best_image_data,
+ best_image_size, new_mime_type, NULL, NULL);
return avatar;
}