I want to scale a bitmap maintaining the aspect ratio, but fitting the required dimensions. This answer scales the bitmap and maintains the aspect ratio, but leaves some blank space unless the image is a perfect square. I need to fill both width and height, just like the FIT_XY
ScaleType property of an ImageView
.
Scale Bitmap maintaining aspect ratio and fitting both width and height
5.7k Views Asked by Pablo Quemé At
3
There are 3 best solutions below
0

This will scale the image to fit into sqaure without any solid color padding in the rest of area and no cropping. If Image is not sqaure then there will be transparent area and aspect ratio of image will as original image. I have tested it with potrait and lanscape images
import android.graphics.*;
public static Bitmap scalePreserveRatio(Bitmap imageToScale, int destinationWidth,
int destinationHeight) {
if (destinationHeight > 0 && destinationWidth > 0 && imageToScale != null) {
int width = imageToScale.getWidth();
int height = imageToScale.getHeight();
//Calculate the max changing amount and decide which dimension to use
float widthRatio = (float) destinationWidth / (float) width;
float heightRatio = (float) destinationHeight / (float) height;
//Use the ratio that will fit the image into the desired sizes
int finalWidth = (int)Math.floor(width * widthRatio);
int finalHeight = (int)Math.floor(height * widthRatio);
if (finalWidth > destinationWidth || finalHeight > destinationHeight) {
finalWidth = (int)Math.floor(width * heightRatio);
finalHeight = (int)Math.floor(height * heightRatio);
}
//Scale given bitmap to fit into the desired area
imageToScale = Bitmap.createScaledBitmap(imageToScale, finalWidth, finalHeight, true);
//Created a bitmap with desired sizes
Bitmap scaledImage = Bitmap.createBitmap(destinationWidth, destinationHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(scaledImage);
//Draw background color
Paint paint = new Paint();
paint.setColor(Color.TRANSPARENT);
paint.setStyle(Paint.Style.FILL);
canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), paint);
//Calculate the ratios and decide which part will have empty areas (width or height)
float ratioBitmap = (float)finalWidth / (float)finalHeight;
float destinationRatio = (float) destinationWidth / (float) destinationHeight;
float left = ratioBitmap >= destinationRatio ? 0 : (float)(destinationWidth - finalWidth) / 2;
float top = ratioBitmap < destinationRatio ? 0: (float)(destinationHeight - finalHeight) / 2;
canvas.drawBitmap(imageToScale, left, top, null);
return scaledImage;
} else {
return imageToScale;
}
}
0

Answer is in Kotlin, based on Pablo's answer and fixed the issue of getting cropped off:
myBitmap?.let {
val originalWidth = it.width.toFloat()
val originalHeight = it.height.toFloat()
var scale = 0.0f
var xTranslation = 0.0f
var yTranslation = 0.0f
val widthRatio = viewWidth / originalWidth
val heightRatio = viewHeight / originalHeight
if (widthRatio > heightRatio) {
scale = viewHeight / originalHeight
xTranslation = (viewWidth - originalWidth * scale) / 2.0f
} else {
scale = viewWidth / originalWidth
yTranslation = (viewHeight - originalHeight * scale) / 2.0f
}
val matrix = Matrix()
matrix.postTranslate(xTranslation, yTranslation)
matrix.preScale(scale, scale)
canvas.drawBitmap(it, matrix, myBitmapPainter)
}
Based on Streets of Boston's answer, I made this method that scales and returns any Bitmap to a desired width and height, fitting both dimensions (no blank space!). It automatically adapts to more horizontal or more vertical images.