diff options
-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; } |