Picasso and Coil inconsistency in image sizing? - android

The first screenshot is with Picasso, the second one with Coil (both in latest versions). Any idea why is this happening?
Picasso: fit().centerInside()
Coil: scale(Scale.FILL).crossfade(true) (I tried with FIT also, same results)
ImageView: adjustViewBounds = true; scaleType = CENTER_INSIDE with MATCH_PARENT width and constant height in pixels.

Coil automatically adjusts to the scale type of the ImageView so you don't need to configure the scale.
Picasso does not, and Picasso's .fit().centerInside() is actually not equivalent to ImageView's CENTER_INSIDE but to FIT_CENTER (it will enlarge the image so that at least one dimension matches the ImageView). There is no equivalent to CENTER_INSIDE with Picasso but these are the closest options:
You can simply remove .fit().centerInside() and let the ImageView scale down the image if it's larger, but if the image is very large it will consume a lot of memory (and may fail to load if larger than the max texture size of the device).
You can use .resize(width, height).centerInside().onlyScaleDown() after measuring the size of the ImageView manually.
If you want Coil to resize the image the same way Picasso does with .fit().centerInside(), then just change the scale type of the ImageView to FIT_CENTER.

Related

How to only scale-down an image if it is larger than requested size in Glide?

I have been using Picasso from a long time. Today, I am migrating to Glide. In Picasso, I used to use following loading pattern:
Picasso.get()
.load(file)
.resize(targetSize, 0)
.onlyScaleDown()
.placeholder(R.color.default_surface)
.error(R.color.default_surface_error)
.into(imageView)
According to resize(int, int) documentation,
Use 0 as desired dimension to resize keeping aspect ratio
According to onlyScaleDown() documentation,
Only resize an image if the original image size is bigger than the target size specified by resize(int, int)
Here's what I am trying:
Glide.with(imageView)
.log(this, thumbnailUrl?.toString())
.load(thumbnailUrl)
.override(600)
.placeholder(R.color.default_surface)
.error(R.color.default_surface_error)
.into(imageView)
Glide uses a default downsampling strategy when loading images using DownsampleStrategy.CENTER_OUTSIDE. It says that image is upscaled to match the overridden size such that one of the dimension (smallest?) is equal to overridden size. And, following comment:
Scales, maintaining the original aspect ratio, so that one of the image's dimensions is exactly equal to the requested size and the other dimension is greater than or equal to the requested size.
This method will upscale if the requested width and height are greater than the source width and height. To avoid upscaling, use {#link #AT_LEAST}, {#link #AT_MOST}, or {#link #CENTER_INSIDE}.
Options in DownsampleStrategy.java confused me. I don't know which one I should use. I want the large images to scale down to overridden size, and small images to never upscale. How to achieve this in Glide?
I have found an answer in Github Issue #3215 where following is suggested:
Pick a useful DownsampleStrategy, in particular CENTER_INSIDE may be what you're looking for. The default DownsampleStrategy will upscale to maximimize Bitmap re-use, but typically there's an equivalent strategy available that will not upscale.
And, DownsampleStrategy.CENTER_INSIDE fits what I wanted:
Returns the original image if it is smaller than the target, otherwise it will be downscaled maintaining its original aspect ratio, so that one of the image's dimensions is exactly equal to the requested size and the other is less or equal than the requested size. Does not upscale if the requested dimensions are larger than the original dimensions.
I was confused by the documentation for DownsampleStrategy.CENTER_INSIDE in code.

How to choose values for resize() value in Picasso

I have added an Image View, and set these values.
<ImageView
android:id="#ivNewsHeader
android:layout_width="match_parent"
android:layout_height="250dp"
android:scaleType="centerCrop" />
I get images from server, and they are very high res images, if i add them as is, i end up getting OutOfMemoryError.
So i learnt that picasso offers a great way to tackle this. I used following, and this scale down any image which is higher than the mentioned dimensions.
Picasso.with(getApplicationContext()).load(imageURL).
resize(180, 130).
onlyScaleDown()
.into(ivNews);
Now when i choose these resize(180, 130), the performance is very good and i don't get any OutOfMemoryError, but the image quality is very poor.
So my question is how to choose resize number, and what equation should is use to put correct width-height numbers in resize() method to get the perfect image without compromising the quality and performance.
My imageView height is 250dp and width is match_parent
Specify scale value based on device size
Device width in pixel
public static int getScreenWidth() {
return Resources.getSystem().getDisplayMetrics().widthPixels;
}
Convert DP to Pixel
public static int dpToPx(int dp)
{
return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}
Now use these two function
Picasso.with(getApplicationContext()).load(imageURL).
resize(getScreenWidth(), dpToPx(250)).
onlyScaleDown()
.into(ivNews);
I think fit() is what you need, because will crop your image to ImageView size on screen. In this case, you don't need do to any more calculations.
Picasso.with(getApplicationContext())
.load(imageURL)
.fit()
.centerInside()
.into(imageView);
Try using fit() which is measuring the dimensions of the target ImageView and internally uses resize() to reduce the image size to the dimensions of the ImageView.
Quoting from this article

Android Picasso load image to Bitmap variable cropping it to square

I need to load some images from URI to Bitmap variables and perform some operation with them togheter. I need the bitmaps to be squared images with fixes size, scaled down and cropped. By now I use this code:
return Picasso.with(c).load(imageUri).resize(size, size).get();
but, obviously, the image will be resized without keep its aspect ratio.
I want to resize the image with these requirements:
the smaller dimension (width or height) should be equals to size
the greater dimension should be cropped to size, keep image centered
The key is using centerInside after resize. See link
Picasso.with(c).load(imageUri).resize(size, size).centerInside().get()
set your imageview height and width fix inside xml and then set image to imageview like
Picasso.with(YourActivityName.this)
.load(imageUri)
.into(imageview_id);

What is resize ,transformation of image in Picasso

I would like to know more details about what is transformation of image in Picasso what will happen if i use transformation for image in android and what is resize and transformation of image.
Picasso.resize(50, 50)
resizes the image to these dimensions (in pixel). does not respect aspect ratio
The transformations will give you enough tools to change the image according to your needs.

ImageView crop and scale image to smaller size

I am trying to get my images to appear in my image view so that if an image is say 600x400 and my image view is 200x200 that the image is scaled to 300x200 and then the extra width is cropped out so that the image appears as a 200x200 image. I have played with the various ScaleTypes but i can't find one that suits what i want. I want something like a combo of ScaleType.FIT_XY and ScaleType.CENTER_CROP
What you need to do is to scale down the image using the inSampleSize as shown here:
http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
and then use ScaleType.CENTER_CROP to show the image in the view.

Categories

Resources