aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXavier Claessens <xclaesse@gmail.com>2010-05-20 22:12:57 +0800
committerXavier Claessens <xclaesse@gmail.com>2010-05-26 17:54:01 +0800
commit4ba1a8de87f108ad073e388711c4d6b05009851e (patch)
treea98a1d4400f6b96ea29f8023aa3fb540043d7f79
parent1ea03406fc359c1623909ff6705c9c67b0e0c30b (diff)
downloadgsoc2013-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.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 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;
}