diff options
author | Xavier Claessens <xclaesse@gmail.com> | 2010-05-20 22:12:57 +0800 |
---|---|---|
committer | Xavier Claessens <xclaesse@gmail.com> | 2010-05-26 17:54:01 +0800 |
commit | 4ba1a8de87f108ad073e388711c4d6b05009851e (patch) | |
tree | a98a1d4400f6b96ea29f8023aa3fb540043d7f79 | |
parent | 1ea03406fc359c1623909ff6705c9c67b0e0c30b (diff) | |
download | gsoc2013-empathy-4ba1a8de87f108ad073e388711c4d6b05009851e.tar gsoc2013-empathy-4ba1a8de87f108ad073e388711c4d6b05009851e.tar.gz gsoc2013-empathy-4ba1a8de87f108ad073e388711c4d6b05009851e.tar.bz2 gsoc2013-empathy-4ba1a8de87f108ad073e388711c4d6b05009851e.tar.lz gsoc2013-empathy-4ba1a8de87f108ad073e388711c4d6b05009851e.tar.xz gsoc2013-empathy-4ba1a8de87f108ad073e388711c4d6b05009851e.tar.zst gsoc2013-empathy-4ba1a8de87f108ad073e388711c4d6b05009851e.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.c | 55 |
1 files changed, 37 insertions, 18 deletions
diff --git a/libempathy-gtk/empathy-avatar-chooser.c b/libempathy-gtk/empathy-avatar-chooser.c index e9d8485a3..6e6c28310 100644 --- a/libempathy-gtk/empathy-avatar-chooser.c +++ b/libempathy-gtk/empathy-avatar-chooser.c @@ -411,8 +411,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; req = tp_connection_get_avatar_requirements (priv->connection); if (req == NULL) { @@ -484,10 +485,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; @@ -524,8 +525,23 @@ avatar_chooser_maybe_convert_and_scale (EmpathyAvatarChooser *chooser, DEBUG ("Produced an image data of %"G_GSIZE_FORMAT" bytes.", converted_image_size); - if (req->maximum_bytes == 0) - break; + /* If the new image satisfy the req, keep it as current best */ + if (req->maximum_bytes == 0 || + converted_image_size <= req->maximum_bytes) { + 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 (req->maximum_bytes == 0 || + req->maximum_bytes - 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 */ @@ -535,20 +551,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 (req->maximum_bytes - 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; } |