26

I want to create a scaled bitmap, but I seemingly get a dis-proportional image. It looks like a square while I want to be rectangular.

My code:

Bitmap resizedBitmap = Bitmap.createScaledBitmap(myBitmap, 960, 960, false);

I want the image to have a MAX of 960. How would I do that? Setting width to null doesn't compile. It's probably simple, but I can't wrap my head around it. Thanks

EGHDK
  • 17,818
  • 45
  • 129
  • 204

3 Answers3

69

If you already have the original bitmap in memory, you don't need to do the whole process of inJustDecodeBounds, inSampleSize, etc. You just need to figure out what ratio to use and scale accordingly.

final int maxSize = 960;
int outWidth;
int outHeight;
int inWidth = myBitmap.getWidth();
int inHeight = myBitmap.getHeight();
if(inWidth > inHeight){
    outWidth = maxSize;
    outHeight = (inHeight * maxSize) / inWidth; 
} else {
    outHeight = maxSize;
    outWidth = (inWidth * maxSize) / inHeight; 
}

Bitmap resizedBitmap = Bitmap.createScaledBitmap(myBitmap, outWidth, outHeight, false);

If the only use for this image is a scaled version, you're better off using Tobiel's answer, to minimize memory usage.

Geobits
  • 22,218
  • 6
  • 59
  • 103
  • Can you elaborate on your comment? "If the only use for this image is a scaled version, you're better off using Tobiel's answer"? – EGHDK Jul 24 '13 at 16:33
  • I mean, if you're using it *only* scaled, use the other answer. It's more efficient if you're just using it that way. If you're already loading/displaying a full-scale version of it, this method is fine, because you'd need the memory for both anyway. – Geobits Jul 24 '13 at 16:35
  • 1
    I get out of memmory with this method. – Johan Apr 30 '14 at 07:19
  • 1
    I believe writing `outHeight = inHeight * (outWidth / inWidth);` instead of `outHeight = (inHeight * maxSize) / inWidth;` would be more readable/understandable – Farid Mar 19 '21 at 10:04
27

Your image is square because you are setting width = 960 and height = 960.

You need to create a method where you pass the size of the image you want like this: http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

In code this looks like:

public static Bitmap lessResolution (String filePath, int width, int height) {
    int reqHeight = height;
    int reqWidth = width;
    BitmapFactory.Options options = new BitmapFactory.Options();    

    // First decode with inJustDecodeBounds=true to check dimensions
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(filePath, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;        

    return BitmapFactory.decodeFile(filePath, options); 
}

private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {

    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {
        // Calculate ratios of height and width to requested height and width
        final int heightRatio = Math.round((float) height / (float) reqHeight);
        final int widthRatio = Math.round((float) width / (float) reqWidth);

        // Choose the smallest ratio as inSampleSize value, this will guarantee
        // a final image with both dimensions larger than or equal to the
        // requested height and width.
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
    }
    return inSampleSize;
}
3dgoo
  • 15,716
  • 6
  • 46
  • 58
Tobiel
  • 1,543
  • 12
  • 19
  • Woah! Thanks for the code, but that's a lot to do to make sure the image keeps it's ratio. I was hoping there would be some magic parameter to pass in. Thanks for the code snippet! – EGHDK Jul 24 '13 at 16:22
  • 3
    The issue is you can get OOM for many reasons with this code you prevent that. this is the android docs about bitmap: http://developer.android.com/training/displaying-bitmaps/index.html – Tobiel Jul 24 '13 at 16:26
  • OOM? Also, what do you think about the answers here? I would appreciate your advice: http://stackoverflow.com/questions/4837715/how-to-resize-a-bitmap-in-android – EGHDK Jul 24 '13 at 16:27
  • OOM means "out of memory" this will stop your app because you are exceeding the amount of memory allowed. My advice is try the solution you think works for you. On the answer do not try the one marked as solution because they are decoding the image from a base64String. – Tobiel Jul 24 '13 at 16:48
  • I had "bitmap size exceed 32bits" error with other solution, and yours work! – eugene Jul 08 '14 at 08:59
  • It seems that sample size is in power of 2. When your code gives inSample = 3, the bitmap result is as if it is processed with inSample = 2. I also compare with the calculation in http://developer.android.com/training/displaying-bitmaps/load-bitmap.html – sancho21 Sep 20 '14 at 09:13
  • in the first 2 lines in the method It Should be int reqHeight=height; int reqWidth=width; – Mhisham Nov 08 '14 at 15:55
  • 1
    NOTE that this method won't give you exactly the size we want, but an image with a size that *might* be scaled down by a power of 2 (if you have a 10kx10k image and ask for a 5001x5001 image, you'll get a 10kx10k image). – user276648 Mar 12 '15 at 00:53
  • I found this after trying Google's example and still having memory issues. Your sample size calculation works better. Hopefully someone in my position (read google docs, thinks this is the same) will notice this and try your variation. – jj. Oct 12 '16 at 20:53
2
bmpimg = Bitmap.createScaledBitmap(srcimg, 100, 50, true);
Avijit
  • 3,834
  • 4
  • 33
  • 45