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
.
Asked
Active
Viewed 5,498 times
3

Community
- 1
- 1

Pablo Quemé
- 1,414
- 4
- 16
- 29
3 Answers
6
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.
public Bitmap resizeBitmapFitXY(int width, int height, Bitmap bitmap){
Bitmap background = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
float originalWidth = bitmap.getWidth(), originalHeight = bitmap.getHeight();
Canvas canvas = new Canvas(background);
float scale, xTranslation = 0.0f, yTranslation = 0.0f;
if (originalWidth > originalHeight) {
scale = height/originalHeight;
xTranslation = (width - originalWidth * scale)/2.0f;
}
else {
scale = width / originalWidth;
yTranslation = (height - originalHeight * scale)/2.0f;
}
Matrix transformation = new Matrix();
transformation.postTranslate(xTranslation, yTranslation);
transformation.preScale(scale, scale);
Paint paint = new Paint();
paint.setFilterBitmap(true);
canvas.drawBitmap(bitmap, transformation, paint);
return background;
}

Community
- 1
- 1

Pablo Quemé
- 1,414
- 4
- 16
- 29
-
1Image this getting cut from left and right side, by this code. – Lovekush Vishwakarma Mar 08 '17 at 11:53
-
@LovekushVishwakarma the point of this code is to fit any bitmap to any dimensions without getting disproportioned, that means that sometimes it will cut horizontally or vertically to maintain the aspect radio – Pablo Quemé Mar 13 '17 at 18:21
-
no but I want to show actual image, and by your code its getting too much cut from left and right side, my requirement is only resizing not cut the left and right side, I want actual image with the resized height and width. – Lovekush Vishwakarma Mar 14 '17 at 10:37
-
1I guess this code isn't right for you then Lovekush – Pablo Quemé Mar 15 '17 at 21:35
-
this answer has code to fit the image to given scale respecting the ratio and no croppping https://stackoverflow.com/a/32810187/9308731 – CrackerKSR Mar 22 '22 at 07:49
-
if you change the conditional to: float widthRatio = width / originalWidth; float heightRatio = heigh / originHeight; if (widthRatio > heightRatio) { it should give the desired results – Lambage Mar 10 '23 at 15:28
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;
}
}

CrackerKSR
- 1,380
- 1
- 11
- 29
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)
}

Lambage
- 367
- 3
- 8