In the last blog posts, you've learned how to load images from various sources and how to use different kind of placeholders. This week's blog post is important if you cannot influence the size of the image to be loaded: resizing and scaling!
Picasso Series Overview
Image Resizing with resize(x, y)
Generally it's optimal if your server or API deliver the image in the exact dimensions you need, which are a perfect trade-off between bandwidth, memory consumption and image quality.
Unfortunately, it's not always in your control to request images in the perfect dimensions. If the images are in a weird size you can use the
resize(horizontalSize, verticalSize) call to change the dimensions of your image into a more suitable size. This will resize the image before displaying it in the
Picasso .with(context) .load(UsageExampleListViewAdapter.eatFoodyImages) .resize(600, 200) // resizes the image to these dimensions (in pixel). does not respect aspect ratio .into(imageViewResize);
Use of scaleDown()
When using the
resize() option Picasso will also upscale your image. Since making a small image bigger without improving the quality of the image can be wasted computing time, call
scaleDown(true) to only apply the
resize() when the original image has larger dimensions than the target size.
Picasso .with(context) .load(UsageExampleListViewAdapter.eatFoodyImages) .resize(6000, 2000) .onlyScaleDown() // the image will only be resized if it's bigger than 6000x2000 pixels. .into(imageViewResizeScaleDown);
Avoiding Stretched Images with Scaling
Now, as with any image manipulation, resizing images can really distort the aspect ratio and uglify the image display. In most of your use cases, you want to prevent this from happening. Picasso gives you two mitigation choices here, either call
CenterCrop() is a cropping technique that scales the image so that it fills the requested bounds of the
ImageView and then crops the extra. The
ImageView will be filled completely, but the entire image might not be displayed.
Picasso .with(context) .load(UsageExampleListViewAdapter.eatFoodyImages) .resize(600, 200) // resizes the image to these dimensions (in pixel) .centerCrop() .into(imageViewResizeCenterCrop);
CenterInside() is a cropping technique that scales the image so that both dimensions are equal to or less than the requested bounds of the
ImageView. The image will be displayed completely, but might not fill the entire
Picasso .with(context) .load(UsageExampleListViewAdapter.eatFoodyImages) .resize(600, 200) .centerInside() .into(imageViewResizeCenterInside);
Last, but not least: Picasso's fit()
The discussed options should cover your needs for functionality regarding image resizing and scaling. There is one last helper functionality of Picasso, which can be very useful:
Picasso .with(context) .load(UsageExampleListViewAdapter.eatFoodyImages) .fit() // call .centerInside() or .centerCrop() to avoid a stretched image .into(imageViewFit);
fit() is measuring the dimensions of the target
ImageView and internally uses
resize() to reduce the image size to the dimensions of the
ImageView. There are two things to know about
fit(). First, calling
fit() can delay the image request since Picasso will need to wait until the size of the
ImageView can be measured. Second, you only can use
fit() with an
ImageView as the target (we'll look at other targets later).
The advantage is that the image is at the lowest possible resolution, without affecting its quality. A lower resolution means less data to be hold in the cache. This can significantly reduce the impact of images in the memory footprint of your app. In summary, if you prefer a lower memory impact over a little faster loading times,
fit() is a great tool.
In this blog post, you've learned how to make adjustments to the size and display of images. This should be very helpful for creating great apps. There is one more tool to make the images in your app feel even more fluid: loading important images first. Picasso offers that functionality with request priorities, which we'll describe in the next blog post.