How to Resize a Bitmap in Android?
Asked Answered
C

21

401

I have a bitmap taken of a Base64 String from my remote database, (encodedImage is the string representing the image with Base64):

profileImage = (ImageView)findViewById(R.id.profileImage);

byte[] imageAsBytes=null;
try {
    imageAsBytes = Base64.decode(encodedImage.getBytes());
} catch (IOException e) {e.printStackTrace();}

profileImage.setImageBitmap(
    BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length)
);

profileImage is my ImageView

Ok, but I have to resize this image before showing it on my ImageView of my layout. I have to resize it to 120x120.

Can someone tell me the code to resize it?

The examples I found could not be applied to a base64 string obtained bitmap.

Catbird answered 29/1, 2011 at 15:38 Comment(2)
Possible duplicate of Resize Bitmap in AndroidAeolipile
@SagarPilkhwal this one was asked firstTripp
C
627

Change:

profileImage.setImageBitmap(
    BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length)

To:

Bitmap b = BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length)
profileImage.setImageBitmap(Bitmap.createScaledBitmap(b, 120, 120, false));
Cluff answered 29/1, 2011 at 15:59 Comment(11)
suppose you have large resolution image say 1200x1200 and when you display this, it will be full in the imageview. If i scale it down say 75% and the screen is so that it displays scaled image also fully in imageview, what should be done for such screens?Factitious
The createScaledBitmap throw a Out of Memory Exception on my Galaxy Tab2 which is very odd to me since there is a lot of memory and no other particular app are running. The Matrix solution work though.Errantry
Most fit answer I found.Bragi
what if we want to save aspect ratio ??Hickie
set filter flag true to improves the quality.Gay
What about dpi scaling for this ? I think the scaled bitmap should be based on the device screen height and width ?Beaverbrook
whats is false?Racket
Using Bitmap.createScaledBitmap() to downscale an image more than half the original size, can produce aliasing artifacts. You can take a look at a post I wrote where I propose some alternatives and compare quality and performance.Trey
@Petrakeas, thank you for your post, code and testing. The only bad was the medium.com (there u have your post) :) ... They so distracting with the top/bottom bars that appear/disappear all the time.Patrolman
quick and easy solution.Abeabeam
About resize quality: use true as the last parameter value for better scaling quality. The docs recommend this as wellObstreperous
S
331
import android.graphics.Matrix
public Bitmap getResizedBitmap(Bitmap bm, int newWidth, int newHeight) {
    int width = bm.getWidth();
    int height = bm.getHeight();
    float scaleWidth = ((float) newWidth) / width;
    float scaleHeight = ((float) newHeight) / height;
    // CREATE A MATRIX FOR THE MANIPULATION
    Matrix matrix = new Matrix();
    // RESIZE THE BIT MAP
    matrix.postScale(scaleWidth, scaleHeight);

    // "RECREATE" THE NEW BITMAP
    Bitmap resizedBitmap = Bitmap.createBitmap(
        bm, 0, 0, width, height, matrix, false);
    bm.recycle();
    return resizedBitmap;
}

EDIT: as suggested by by @aveschini, I have added bm.recycle(); in order to avoid the memory leaks. Please note that in case if you are using the previous object for some other purposes, then handle accordingly.

Schug answered 22/5, 2012 at 13:40 Comment(9)
I tried both bitmap.createscaledbitmap and this matrix approach. I find the image is much more clear with matrix approach. I do not know if it is common or just because I am using a simulator instead of a phone. Just a hint for someone who encouters the same trouble like me.Elfie
here too you have to add bm.recycle() for much better memory performancesMagruder
Thanks for the solution, but it would be better if the parameters were reordered; public Bitmap getResizedBitmap(Bitmap bm, int newWidth, int newHeight). I spent a hell of time figuring it out. ;PRaddled
The image quality produced by this is fantastic, oh wow! Thanks for the answer!Zorine
@Magruder No need to recycle, as nothing will be referencing resizedBitmap, after the function returns; GC will pick it up shortly after. :)Zorine
How to Set Minimum and maximum zoom size?Hufuf
Note that the correct import for Matrix is android.graphics.Matrix.Birdwell
This is the same as calling Bitmap.createScaledBitmap(). See android.googlesource.com/platform/frameworks/base/+/refs/heads/…Smorgasbord
This solution gives me distored images for some.Kashgar
S
135

If you already have a bitmap, you could use the following code to resize:

Bitmap originalBitmap = <original initialization>;
Bitmap resizedBitmap = Bitmap.createScaledBitmap(
    originalBitmap, newWidth, newHeight, false);
Symptomatic answered 12/11, 2012 at 21:53 Comment(4)
@beginner if you resize the image, you may be scaling based on different dimensions that either transform the bitmap to incorrect proportions or remove some of the bitmap information.Symptomatic
I tried resizing the bitmap based on the proportions , but then I was getting this error. Caused by: java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@2291dd13Optimize
@Optimize each time your resize the bitmap, depending on what you are doing, you usually will need to create a copy which is a new size, rather than resizing the existing bitmap (since in this case it looks like the reference to the bitmap was already recycled in memory).Symptomatic
correct ..i tried it and it works proper now. thanksOptimize
L
49

Scale based on aspect ratio:

float aspectRatio = yourSelectedImage.getWidth() / 
    (float) yourSelectedImage.getHeight();
int width = 480;
int height = Math.round(width / aspectRatio);

yourSelectedImage = Bitmap.createScaledBitmap(
    yourSelectedImage, width, height, false);

To use height as base intead of width change to:

int height = 480;
int width = Math.round(height * aspectRatio);
Latin answered 7/3, 2015 at 23:0 Comment(0)
F
27

Scale a bitmap with a target maximum size and width, while maintaining aspect ratio:

int maxHeight = 2000;
int maxWidth = 2000;    
float scale = Math.min(((float)maxHeight / bitmap.getWidth()), ((float)maxWidth / bitmap.getHeight()));

Matrix matrix = new Matrix();
matrix.postScale(scale, scale);

bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
Fife answered 3/6, 2015 at 1:1 Comment(0)
A
7

try this this code :

BitmapDrawable drawable = (BitmapDrawable) imgview.getDrawable();
Bitmap bmp = drawable.getBitmap();
Bitmap b = Bitmap.createScaledBitmap(bmp, 120, 120, false);

I hope it's useful.

Adventuresome answered 9/12, 2014 at 5:59 Comment(0)
P
7

Someone asked how to keep aspect ratio in this situation:

Calculate the factor you are using for scaling and use it for both dimensions. Let´s say you want an image to be 20% of the screen in height

int scaleToUse = 20; // this will be our percentage
Bitmap bmp = BitmapFactory.decodeResource(
    context.getResources(), R.drawable.mypng);
int sizeY = screenResolution.y * scaleToUse / 100;
int sizeX = bmp.getWidth() * sizeY / bmp.getHeight();
Bitmap scaled = Bitmap.createScaledBitmap(bmp, sizeX, sizeY, false);

for getting the screen resolution you have this solution: Get screen dimensions in pixels

Pantalets answered 6/3, 2015 at 6:16 Comment(0)
C
5

Although the accepted answer is correct, it doesn't resize Bitmap by keeping the same Aspect Ratio. If you are looking for a method to resize Bitmap by keeping the same aspect ratio you can use the following utility function. The usage details and explanation of the function are present at this link.

public static Bitmap resizeBitmap(Bitmap source, int maxLength) {
       try {
           if (source.getHeight() >= source.getWidth()) {
               int targetHeight = maxLength;
               if (source.getHeight() <= targetHeight) { // if image already smaller than the required height
                   return source;
               }

               double aspectRatio = (double) source.getWidth() / (double) source.getHeight();
               int targetWidth = (int) (targetHeight * aspectRatio);

               Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
               if (result != source) {
               }
               return result;
           } else {
               int targetWidth = maxLength;

               if (source.getWidth() <= targetWidth) { // if image already smaller than the required height
                   return source;
               }

               double aspectRatio = ((double) source.getHeight()) / ((double) source.getWidth());
               int targetHeight = (int) (targetWidth * aspectRatio);

               Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
               if (result != source) {
               }
               return result;

           }
       }
       catch (Exception e)
       {
           return source;
       }
   }
Chartier answered 12/11, 2019 at 14:24 Comment(0)
T
4
  public Bitmap scaleBitmap(Bitmap mBitmap) {
        int ScaleSize = 250;//max Height or width to Scale
        int width = mBitmap.getWidth();
        int height = mBitmap.getHeight();
        float excessSizeRatio = width > height ? width / ScaleSize : height / ScaleSize;
         Bitmap bitmap = Bitmap.createBitmap(
                mBitmap, 0, 0,(int) (width/excessSizeRatio),(int) (height/excessSizeRatio));
        //mBitmap.recycle(); if you are not using mBitmap Obj
        return bitmap;
    }
Thyrsus answered 10/5, 2016 at 5:58 Comment(1)
for me it worked after a bit retyping float excessSizeRatio = width > height ? (float)( (float)width / (float)ScaleSize) : (float)((float)height / (float)ScaleSize);Spoils
T
4
public static Bitmap resizeBitmapByScale(
            Bitmap bitmap, float scale, boolean recycle) {
        int width = Math.round(bitmap.getWidth() * scale);
        int height = Math.round(bitmap.getHeight() * scale);
        if (width == bitmap.getWidth()
                && height == bitmap.getHeight()) return bitmap;
        Bitmap target = Bitmap.createBitmap(width, height, getConfig(bitmap));
        Canvas canvas = new Canvas(target);
        canvas.scale(scale, scale);
        Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG);
        canvas.drawBitmap(bitmap, 0, 0, paint);
        if (recycle) bitmap.recycle();
        return target;
    }
    private static Bitmap.Config getConfig(Bitmap bitmap) {
        Bitmap.Config config = bitmap.getConfig();
        if (config == null) {
            config = Bitmap.Config.ARGB_8888;
        }
        return config;
    }
Tb answered 1/9, 2016 at 5:10 Comment(0)
M
4
      Try this kotlin code for resize....Where Max size any size you 
      want

      fun getResizedBitmap(image: Bitmap?, maxSize: Int): Bitmap {
    var width = image!!.width
    var height = image.height
    val bitmapRatio = width.toFloat() / height.toFloat()
     if (bitmapRatio > 0) {
        width = maxSize
        height = (width / bitmapRatio).toInt()
     } else {
        height = maxSize
         width = (height * bitmapRatio).toInt()
     }
         return Bitmap.createScaledBitmap(image, width, height, true)
     }
Morice answered 28/3, 2022 at 12:22 Comment(0)
L
3
profileImage.setImageBitmap(
    Bitmap.createScaledBitmap(
        BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length), 
        80, 80, false
    )
);
Laverty answered 7/4, 2014 at 8:26 Comment(0)
P
3

Try this: This function resizes a bitmap proportionally. When the last parameter is set to "X" the newDimensionXorY is treated as s new width and when set to "Y" a new height.

public Bitmap getProportionalBitmap(Bitmap bitmap, 
                                    int newDimensionXorY, 
                                    String XorY) {
    if (bitmap == null) {
        return null;
    }

    float xyRatio = 0;
    int newWidth = 0;
    int newHeight = 0;

    if (XorY.toLowerCase().equals("x")) {
        xyRatio = (float) newDimensionXorY / bitmap.getWidth();
        newHeight = (int) (bitmap.getHeight() * xyRatio);
        bitmap = Bitmap.createScaledBitmap(
            bitmap, newDimensionXorY, newHeight, true);
    } else if (XorY.toLowerCase().equals("y")) {
        xyRatio = (float) newDimensionXorY / bitmap.getHeight();
        newWidth = (int) (bitmap.getWidth() * xyRatio);
        bitmap = Bitmap.createScaledBitmap(
            bitmap, newWidth, newDimensionXorY, true);
    }
    return bitmap;
}
Patrick answered 11/5, 2015 at 8:4 Comment(0)
O
3

Bitmap Resize based on Any Display size

public Bitmap bitmapResize(Bitmap imageBitmap) {

    Bitmap bitmap = imageBitmap;
    float heightbmp = bitmap.getHeight();
    float widthbmp = bitmap.getWidth();

    // Get Screen width
    DisplayMetrics displaymetrics = new DisplayMetrics();
    this.getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
    float height = displaymetrics.heightPixels / 3;
    float width = displaymetrics.widthPixels / 3;

    int convertHeight = (int) hight, convertWidth = (int) width;

    // higher
    if (heightbmp > height) {
        convertHeight = (int) height - 20;
        bitmap = Bitmap.createScaledBitmap(bitmap, convertWidth,
                convertHighet, true);
    }

    // wider
    if (widthbmp > width) {
        convertWidth = (int) width - 20;
        bitmap = Bitmap.createScaledBitmap(bitmap, convertWidth,
                convertHeight, true);
    }

    return bitmap;
}
Orthopedic answered 20/7, 2016 at 6:9 Comment(0)
W
2

Just make it simple:

fun Bitmap.scaleWith(scale: Float) = Bitmap.createScaledBitmap(
    this,
    (width * scale).toInt(),
    (height * scale).toInt(),
    false
)

And you can use it to scale up or down, here scale = 1.0 is considered the same size, so to scale up by 20% will be scale = 1.2

Wisent answered 21/3, 2023 at 9:57 Comment(0)
M
1

As of API 19, Bitmap setWidth(int width) and setHeight(int height) exist. http://developer.android.com/reference/android/graphics/Bitmap.html

Mckelvey answered 25/1, 2016 at 17:20 Comment(0)
B
1
/**
 * Kotlin method for Bitmap scaling
 * @param bitmap the bitmap to be scaled
 * @param pixel  the target pixel size
 * @param width  the width
 * @param height the height
 * @param max    the max(height, width)
 * @return the scaled bitmap
 */
fun scaleBitmap(bitmap:Bitmap, pixel:Float, width:Int, height:Int, max:Int):Bitmap {
    val scale = px / max
    val h = Math.round(scale * height)
    val w = Math.round(scale * width)
    return Bitmap.createScaledBitmap(bitmap, w, h, true)
  }
Bise answered 13/11, 2019 at 18:56 Comment(0)
G
1

Keeping the aspect ratio,

  public Bitmap resizeBitmap(Bitmap source, int width,int height) {
    if(source.getHeight() == height && source.getWidth() == width) return source;
    int maxLength=Math.min(width,height);
    try {
        source=source.copy(source.getConfig(),true);
        if (source.getHeight() <= source.getWidth()) {
            if (source.getHeight() <= maxLength) { // if image already smaller than the required height
                return source;
            }

            double aspectRatio = (double) source.getWidth() / (double) source.getHeight();
            int targetWidth = (int) (maxLength * aspectRatio);

            return Bitmap.createScaledBitmap(source, targetWidth, maxLength, false);
        } else {

            if (source.getWidth() <= maxLength) { // if image already smaller than the required height
                return source;
            }

            double aspectRatio = ((double) source.getHeight()) / ((double) source.getWidth());
            int targetHeight = (int) (maxLength * aspectRatio);

            return Bitmap.createScaledBitmap(source, maxLength, targetHeight, false);

        }
    }
    catch (Exception e)
    {
        return source;
    }
}
Guadalupeguadeloupe answered 19/3, 2020 at 12:26 Comment(0)
J
0

While the previous answers do scale the image and take care of the aspect ratio, the resampling itself should be done so that there is no aliasing. Taking care of scale is a matter of fixing arguments correctly. There are many comments about the quality of the output images from standard scaling call. to maintain quality of the image one should use the standard call:

Bitmap resizedBitmap = Bitmap.createScaledBitmap(originalBitmap, newWidth, newHeight, true);

with the last argument set to true because it will do the bilinear filtering for resampling to prevent aliasing. Read more about aliasing here: https://en.wikipedia.org/wiki/Aliasing

From android documentation:

https://developer.android.com/reference/android/graphics/Bitmap#createScaledBitmap(android.graphics.Bitmap,%20int,%20int,%20boolean)


public static Bitmap createScaledBitmap (Bitmap src, 
                int dstWidth, 
                int dstHeight, 
                boolean filter)

filter : boolean, Whether or not bilinear filtering should be used when scaling the bitmap. If this is true then bilinear filtering will be used when scaling which has better image quality at the cost of worse performance. If this is false then nearest-neighbor scaling is used instead which will have worse image quality but is faster. Recommended default is to set filter to 'true' as the cost of bilinear filtering is typically minimal and the improved image quality is significant.

Jedediah answered 5/1, 2021 at 6:25 Comment(0)
R
0
* For resize bitmap with width and height ratio.    

public static Bitmap getResizedBitmap(Bitmap image, int maxSize) {
            int width = image.getWidth();
            int height = image.getHeight();
    
            float bitmapRatio = (float) width / (float) height;
            if (bitmapRatio > 1) {
                width = maxSize;
                height = (int) (width / bitmapRatio);
            } else {
                height = maxSize;
                width = (int) (height * bitmapRatio);
            }
            return Bitmap.createScaledBitmap(image, width, height, true);
        }
Renz answered 4/4, 2021 at 8:55 Comment(0)
S
0

apply Matrix.ScaleToFit.CENTER) for getting a new bitmap keeps aspect ratio.

public static Bitmap getScaledwonBitmap(Bitmap srcBmp, int deisredWidth, int desiredHeight) {
        
            Matrix matrix = new Matrix();
            matrix.setRectToRect(new RectF(0, 0, srcBmp.getWidth(), srcBmp.getHeight()),
                    new RectF(0, 0, deisredWidth, desiredHeight),
                    Matrix.ScaleToFit.CENTER);
           return Bitmap.createBitmap(srcBmp, 0, 0, srcBmp.getWidth(), srcBmp.getHeight(), matrix, true);
        
    }
Sulfanilamide answered 3/10, 2021 at 12:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.