Friday, September 12, 2014

Android: Image loading libraries Picasso vs Glide

This post is about image loading libraries, which could help us in avoiding complex codes.

Downloading of images, caching and reusing of images are know part of all the application and it became part of developers life. While doing this process, We need to consider few things...

  • Loading process should be asynchronously.
  • Image should display when it is loaded successfully, In case if it is not downloaded then placing some place holders.
  • Caching Image rather than downloading every time.

There are more libraries in the market which helps us in avoiding to do all these exercises and here I am going to discuss about Picasso and Glide. Where this two libraries looks similar in the way of implementation and Its easy to integrate in the middle of the application, since its a just a one line code to load image.

There are lot of features in the two libraries and few are listed below, where I can compare them easily.

Picasso.with(this)
.load(URL)
.into(imageView);
Glide.with(this)
.load(URL)
.into(imageView);
Re-size the Image
Picasso.with(this)
.load(URL)
.resize(200, 200)
.into(imageView);
Glide.with(this)
.load(URL)
.override(200, 200)
.into(imageView);
If loading is failed then on failure callbacks or listener.


Picasso.with(this)
.load(URL)
.into(ImageView imageView, Callback arg1)
Glide.with(this)
.load(URL)
.listener(RequestListener<String, GlideDrawable> requestListener
)
.into(imageView);
Transform Picasso.with(this)
.load(URL)
.transform(new CircleTransform())
.into(imageView);
Glide.with(this)
.load(URL)
.transform(new CircleTransform(context))
.into(imageView);
Thumbnail Support No Yes

Glide.with(this)
.load(URL)
.thumbnail(0.1f)
.into(imageView);
Animation No direct approach Yes

Animation anim = AnimationUtils.loadAnimation(context, android.R.anim.fade_in);

Glide.with(this)
.load(URL)
.animate(anim)
.into(imageView);
Placeholders during loading Yes

.placeholder(drawable/resourceid)
.error(drawable/resourceid)
Yes

.placeholder(drawable/resourceid)
.error(drawable/resourceid)

How can we get directly Circular Image, when we can get when we download from the url?
This both libraries support in doing without change of xml.
Both the libraries are having transform method, where we can customize the class and we can get the image as we required.

Picasso (CircleTransform.Java)

 import android.graphics.Bitmap;  
 import com.squareup.picasso.Transformation;  
 public class CircleTransform implements Transformation {  
   @Override  
   public Bitmap transform(Bitmap source) {  
     return ImageUtils.getCircularBitmapImage(source);  
   }  
   @Override  
   public String key() {  
     return "circle-image";  
   }  
 }  

Glide (CircleTransform.Java)

 import android.content.Context;  
 import android.graphics.Bitmap;  
 import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;  
 import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;  
 public class GlideCircleTransform extends BitmapTransformation {  
   public GlideCircleTransform(Context context) {  
     super(context);  
   }  
   @Override  
   protected Bitmap transform(BitmapPool pool, Bitmap source, int outWidth, int outHeight) {  
     return ImageUtils.getCircularBitmapImage(source);  
   }  
   @Override  
   public String getId() {  
     return "Glide_Circle_Transformation";  
   }  
 }  

Utils class, where we are customizing the bitmap image as we required.
ImageUtils.java

 import android.graphics.Bitmap;  
 import android.graphics.BitmapShader;  
 import android.graphics.Canvas;  
 import android.graphics.Paint;  
 public class ImageUtils {  
   public static Bitmap getCircularBitmapImage(Bitmap source) {  
     int size = Math.min(source.getWidth(), source.getHeight());  
     int x = (source.getWidth() - size) / 2;  
     int y = (source.getHeight() - size) / 2;  
     Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size);  
     if (squaredBitmap != source) {  
       source.recycle();  
     }  
     Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);  
     Canvas canvas = new Canvas(bitmap);  
     Paint paint = new Paint();  
     BitmapShader shader = new BitmapShader(squaredBitmap, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);  
     paint.setShader(shader);  
     paint.setAntiAlias(true);  
     float r = size / 2f;  
     canvas.drawCircle(r, r, r, paint);  
     squaredBitmap.recycle();  
     return bitmap;  
   }  
 }  

The above getCircularBitmapImage method provides me the circular bitmap image.

Screenshot:







Thanks for reading :) 
Whether this post is helpful?

Have something to add to this post? If you have any other quick thoughts/hints that you think people will find useful? Share it in the comments. feedback are welcome...

19 comments :

  1. Great article. Very helpful. It might also be nice for some to add animated gif and video still support comparison to the table. Because I know glide supports animated gifs and video stills, but not sure if Picasso also supports that or not

    ReplyDelete
  2. Nice article! People are using this class, but it has a big problem. The toTransform Bitmap should never be recycled. Glide does that for you we sees fit. If Picasso needs to recycle then that should be in the Transformation, not the utility. Can you please update the code in this article from http://stackoverflow.com/a/25806229/253468 ?

    More info at https://github.com/bumptech/glide/issues/408

    ReplyDelete
    Replies
    1. Thanks for the comment. My intention is to re-use the same code, when user shift between libraries.

      Delete
    2. Your article is about pointing out the differences/similarities between the two libararies, this is a big one. The effort to reuse code is heroic (and 100% agree with it), but it's not fully possible here, since the libraries differ in their core. In Glide, you cannot (https://github.com/bumptech/glide/commit/1fabbe4c5321befdbe708b061797e87c33e88403) recycle the received Bitmap, because it may result in exceptions or other problems. Also you are working against the effort Glide makes to make bitmap displays performant by reusing them. There are many reported issues related to calling recycle on those bitmaps (#408 is just one of them).

      You could however move the recycling logic (if and recycle call) out of the method and into the Picasso transform (the circular transform can still be shared), or give a boolean recycleSource argument to the method. Both of the above would point out nicely that there's a significant difference here.

      Delete
  3. Great Article and Glide is best library in the world.

    ReplyDelete
  4. This blog is to share the knowledge or tech tips in Java, Android, iOS and more..., which I came across in my ***carrier***
    Typo.. please change to career.. Otherwise thanks for the article.

    ReplyDelete
  5. Have you made a performance comparison?
    Memory utilization comparison?
    At least with Picasso, we get a lot of OOM exceptions.

    ReplyDelete
    Replies
    1. My intention is not about the performance and memory utilization. It is just about the usage of the 2 libraries.
      Thanks for the idea, I will check and come up with new post about the performance and utilization in future

      Delete
  6. Nicely presented!

    But, Want to know which is the fastest image loading library for android?
    I had recently gone through this
    Check this out:

    http://bit.ly/glide-vs-picasso

    ReplyDelete
  7. Nicely presented!

    But, Want to know which is the fastest image loading library for android?
    I had recently gone through this
    Check this out:

    http://bit.ly/glide-vs-picasso

    ReplyDelete
  8. both of them use approach ".overwrite(200,200)" ,why display different size?

    ReplyDelete