Resize a large bitmap file to scaled output file on Android

AndroidImageResizeBitmap

Android Problem Overview


I have a large bitmap (say 3888x2592) in a file. Now, I want to resize that bitmap to 800x533 and save it to another file. I normally would scale the bitmap by calling Bitmap.createBitmap method but it needs a source bitmap as the first argument, which I can't provide because loading the original image into a Bitmap object would of course exceed the memory (see here, for example).

I also can't read the bitmap with, for example, BitmapFactory.decodeFile(file, options), providing a BitmapFactory.Options.inSampleSize, because I want to resize it to an exact width and height. Using inSampleSize would resize the bitmap to 972x648 (if I use inSampleSize=4) or to 778x518 (if I use inSampleSize=5, which isn't even a power of 2).

I would also like to avoid reading the image using inSampleSize with, for example, 972x648 in a first step and then resizing it to exactly 800x533 in a second step, because the quality would be poor compared to a direct resizing of the original image.

To sum up my question: Is there a way to read a large image file with 10MP or more and save it to a new image file, resized to a specific new width and height, without getting an OutOfMemory exception?

I also tried BitmapFactory.decodeFile(file, options) and setting the Options.outHeight and Options.outWidth values manually to 800 and 533, but it doesn't work that way.

Android Solutions


Solution 1 - Android

No. I'd love for someone to correct me, but I accepted the load/resize approach you tried as a compromise.

Here are the steps for anyone browsing:

  1. Calculate the maximum possible inSampleSize that still yields an image larger than your target.
  2. Load the image using BitmapFactory.decodeFile(file, options), passing inSampleSize as an option.
  3. Resize to the desired dimensions using Bitmap.createScaledBitmap().

Solution 2 - Android

Justin answer translated to code (works perfect for me):

private Bitmap getBitmap(String path) {

Uri uri = getImageUri(path);
InputStream in = null;
try {
    final int IMAGE_MAX_SIZE = 1200000; // 1.2MP
    in = mContentResolver.openInputStream(uri);

    // Decode image size
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(in, null, options);
    in.close();



    int scale = 1;
    while ((options.outWidth * options.outHeight) * (1 / Math.pow(scale, 2)) > 
          IMAGE_MAX_SIZE) {
       scale++;
    }
    Log.d(TAG, "scale = " + scale + ", orig-width: " + options.outWidth + ", 
       orig-height: " + options.outHeight);

    Bitmap resultBitmap = null;
    in = mContentResolver.openInputStream(uri);
    if (scale > 1) {
        scale--;
        // scale to max possible inSampleSize that still yields an image
        // larger than target
        options = new BitmapFactory.Options();
        options.inSampleSize = scale;
        resultBitmap = BitmapFactory.decodeStream(in, null, options);

        // resize to desired dimensions
        int height = resultBitmap.getHeight();
        int width = resultBitmap.getWidth();
        Log.d(TAG, "1th scale operation dimenions - width: " + width + ",
           height: " + height);

        double y = Math.sqrt(IMAGE_MAX_SIZE
                / (((double) width) / height));
        double x = (y / height) * width;

        Bitmap scaledBitmap = Bitmap.createScaledBitmap(resultBitmap, (int) x, 
           (int) y, true);
        resultBitmap.recycle();
        resultBitmap = scaledBitmap;

        System.gc();
    } else {
        resultBitmap = BitmapFactory.decodeStream(in);
    }
    in.close();

    Log.d(TAG, "bitmap size - width: " +resultBitmap.getWidth() + ", height: " + 
       resultBitmap.getHeight());
    return resultBitmap;
} catch (IOException e) {
    Log.e(TAG, e.getMessage(),e);
    return null;
}

Solution 3 - Android

This is 'Mojo Risin's and 'Ofir's solutions "combined". This will give you a proportionally resized image with the boundaries of max width and max height.

  1. It only reads meta data to get the original size (options.inJustDecodeBounds)
  2. It uses a rought resize to save memory (itmap.createScaledBitmap)
  3. It uses a precisely resized image based on the rough Bitamp created earlier.

For me it has been performing fine on 5 MegaPixel images an below.

try
{
	int inWidth = 0;
	int inHeight = 0;
	
	InputStream in = new FileInputStream(pathOfInputImage);
	
    // decode image size (decode metadata only, not the whole image)
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(in, null, options);
    in.close();
    in = null;
    
    // save width and height
    inWidth = options.outWidth;
    inHeight = options.outHeight;
    
    // decode full image pre-resized
    in = new FileInputStream(pathOfInputImage);
	options = new BitmapFactory.Options();
	// calc rought re-size (this is no exact resize)
	options.inSampleSize = Math.max(inWidth/dstWidth, inHeight/dstHeight);
	// decode full image
	Bitmap roughBitmap = BitmapFactory.decodeStream(in, null, options);
	
	// calc exact destination size
	Matrix m = new Matrix();
	RectF inRect = new RectF(0, 0, roughBitmap.getWidth(), roughBitmap.getHeight());
	RectF outRect = new RectF(0, 0, dstWidth, dstHeight);
	m.setRectToRect(inRect, outRect, Matrix.ScaleToFit.CENTER);
	float[] values = new float[9];
	m.getValues(values);
	
	// resize bitmap
	Bitmap resizedBitmap = Bitmap.createScaledBitmap(roughBitmap, (int) (roughBitmap.getWidth() * values[0]), (int) (roughBitmap.getHeight() * values[4]), true);

	// save image
	try
	{
		FileOutputStream out = new FileOutputStream(pathOfOutputImage);
		resizedBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);
	}
	catch (Exception e)
	{
		Log.e("Image", e.getMessage(), e);
	}
}
catch (IOException e)
{
    Log.e("Image", e.getMessage(), e);
}

Solution 4 - Android

Why not use the API?

int h = 48; // height in pixels
int w = 48; // width in pixels    
Bitmap scaled = Bitmap.createScaledBitmap(largeBitmap, w, h, true);

Solution 5 - Android

Acknowledging the other excellent answer so far, the best code I've seen yet for this is in the documentation for the photo taking tool.

See the section entitled "Decode a Scaled Image".

http://developer.android.com/training/camera/photobasics.html

The solution it proposes is a resize then scale solution like the others here, but it's quite neat.

I've copied the code below as a ready-to-go function for convenience.

private void setPic(String imagePath, ImageView destination) {
    int targetW = destination.getWidth();
    int targetH = destination.getHeight();
    // Get the dimensions of the bitmap
    BitmapFactory.Options bmOptions = new BitmapFactory.Options();
    bmOptions.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(imagePath, bmOptions);
    int photoW = bmOptions.outWidth;
    int photoH = bmOptions.outHeight;
  
    // Determine how much to scale down the image
    int scaleFactor = Math.min(photoW/targetW, photoH/targetH);
  
    // Decode the image file into a Bitmap sized to fill the View
    bmOptions.inJustDecodeBounds = false;
    bmOptions.inSampleSize = scaleFactor;
    bmOptions.inPurgeable = true;
  
    Bitmap bitmap = BitmapFactory.decodeFile(imagePath, bmOptions);
    destination.setImageBitmap(bitmap);
}

Solution 6 - Android

After reading these answers and android documentation here's the code to resize bitmap without loading it into memory:

public Bitmap getResizedBitmap(int targetW, int targetH,  String imagePath) {

    // Get the dimensions of the bitmap
    BitmapFactory.Options bmOptions = new BitmapFactory.Options();
    //inJustDecodeBounds = true <-- will not load the bitmap into memory
    bmOptions.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(imagePath, bmOptions);
    int photoW = bmOptions.outWidth;
    int photoH = bmOptions.outHeight;

    // Determine how much to scale down the image
    int scaleFactor = Math.min(photoW/targetW, photoH/targetH);

    // Decode the image file into a Bitmap sized to fill the View
    bmOptions.inJustDecodeBounds = false;
    bmOptions.inSampleSize = scaleFactor;
    bmOptions.inPurgeable = true;

    Bitmap bitmap = BitmapFactory.decodeFile(imagePath, bmOptions);
    return(bitmap);
}

Solution 7 - Android

When i have large bitmaps and i want to decode them resized i use the following

BitmapFactory.Options options = new BitmapFactory.Options();
InputStream is = null;
is = new FileInputStream(path_to_file);
BitmapFactory.decodeStream(is,null,options);
is.close();
is = new FileInputStream(path_to_file);
// here w and h are the desired width and height
options.inSampleSize = Math.max(options.outWidth/w, options.outHeight/h);
// bitmap is the resized bitmap
Bitmap bitmap = BitmapFactory.decodeStream(is,null,options);

Solution 8 - Android

This may be useful for someone else looking at this question. I rewrote Justin's code to allow the method to receive the target size object required as well. This works very well when using Canvas. All credit should go to JUSTIN for his great initial code.

    private Bitmap getBitmap(int path, Canvas canvas) {

		Resources resource = null;
		try {
		    final int IMAGE_MAX_SIZE = 1200000; // 1.2MP
		    resource = getResources();

		    // Decode image size
		    BitmapFactory.Options options = new BitmapFactory.Options();
		    options.inJustDecodeBounds = true;
		    BitmapFactory.decodeResource(resource, path, options);
		    
		    int scale = 1;
		    while ((options.outWidth * options.outHeight) * (1 / Math.pow(scale, 2)) > 
		          IMAGE_MAX_SIZE) {
		       scale++;
		    }
		    Log.d("TAG", "scale = " + scale + ", orig-width: " + options.outWidth + ", orig-height: " + options.outHeight);

		    Bitmap pic = null;
		    if (scale > 1) {
		        scale--;
		        // scale to max possible inSampleSize that still yields an image
		        // larger than target
		        options = new BitmapFactory.Options();
		        options.inSampleSize = scale;
		        pic = BitmapFactory.decodeResource(resource, path, options);

		        // resize to desired dimensions
		        int height = canvas.getHeight();
		        int width = canvas.getWidth();
		        Log.d("TAG", "1th scale operation dimenions - width: " + width + ", height: " + height);

		        double y = Math.sqrt(IMAGE_MAX_SIZE
		                / (((double) width) / height));
		        double x = (y / height) * width;

		        Bitmap scaledBitmap = Bitmap.createScaledBitmap(pic, (int) x, (int) y, true);
		        pic.recycle();
		        pic = scaledBitmap;

		        System.gc();
		    } else {
		        pic = BitmapFactory.decodeResource(resource, path);
		    }
		    
		    Log.d("TAG", "bitmap size - width: " +pic.getWidth() + ", height: " + pic.getHeight());
		    return pic;
		} catch (Exception e) {
		    Log.e("TAG", e.getMessage(),e);
		    return null;
		}
	}

Justin's code is VERY effective at reducing the overhead of working with large Bitmaps.

Solution 9 - Android

I don't know if my solution is best practice, but I achieved loading a bitmap with my desired scaling by using the inDensity and inTargetDensity options. inDensity is 0 initially when not loading a drawable resource, so this approach is for loading non resource images.

The variables imageUri, maxImageSideLength and context are parameters of my method. I posted only the method implementation without the wrapping AsyncTask for clarity.

            ContentResolver resolver = context.getContentResolver();
            InputStream is;
            try {
                is = resolver.openInputStream(imageUri);
            } catch (FileNotFoundException e) {
                Log.e(TAG, "Image not found.", e);
                return null;
            }
            Options opts = new Options();
            opts.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(is, null, opts);

            // scale the image
            float maxSideLength = maxImageSideLength;
            float scaleFactor = Math.min(maxSideLength / opts.outWidth, maxSideLength / opts.outHeight);
            // do not upscale!
            if (scaleFactor < 1) {
                opts.inDensity = 10000;
                opts.inTargetDensity = (int) ((float) opts.inDensity * scaleFactor);
            }
            opts.inJustDecodeBounds = false;

            try {
                is.close();
            } catch (IOException e) {
                // ignore
            }
            try {
                is = resolver.openInputStream(imageUri);
            } catch (FileNotFoundException e) {
                Log.e(TAG, "Image not found.", e);
                return null;
            }
            Bitmap bitmap = BitmapFactory.decodeStream(is, null, opts);
            try {
                is.close();
            } catch (IOException e) {
                // ignore
            }

            return bitmap;

Solution 10 - Android

Taking into account that you want to resize to exact size and want to keep as much quality as needed I think you should try this.

  1. Find out the size of the resized image with call of BitmapFactory.decodeFile and providing the checkSizeOptions.inJustDecodeBounds
  2. Calculate the maximum possible inSampleSize you can use on your device to not exceed the memory. bitmapSizeInBytes = 2widthheight; Generally for your picture inSampleSize=2 would be fine since you will need only 2*1944x1296)=4.8Mbб which should feet in memory
  3. Use BitmapFactory.decodeFile with inSampleSize to load the Bitmap
  4. Scale the bitmap to exact size.

Motivation: multiple-steps scaling could give you higher quality picture, however there is no guarantee that it will work better than using high inSampleSize. Actually, I think that you also can use inSampleSize like 5 (not pow of 2) to have direct scaling in one operation. Or just use 4 and then you can just use that image in UI. if you send it to server - than you can do scaling to exact size on server side which allow you to use advanced scaling techniques.

Notes: if the Bitmap loaded in step-3 is at least 4 times larger (so the 4*targetWidth < width) you probably can use several resizing to achieve better quality. at least that works in generic java, in android you don't have the option to specify the interpolation used for scaling http://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html

Solution 11 - Android

I used code like this:

  String filePath=Environment.getExternalStorageDirectory()+"/test_image.jpg";
  BitmapFactory.Options options=new BitmapFactory.Options();
  InputStream is=new FileInputStream(filePath);
  BitmapFactory.decodeStream(is, null, options);
  is.close();
  is=new FileInputStream(filePath);
  // here w and h are the desired width and height
  options.inSampleSize=Math.max(options.outWidth/460, options.outHeight/288); //Max 460 x 288 is my desired...
  // bmp is the resized bitmap
  Bitmap bmp=BitmapFactory.decodeStream(is, null, options);
  is.close();
  Log.d(Constants.TAG, "Scaled bitmap bytes, "+bmp.getRowBytes()+", width:"+bmp.getWidth()+", height:"+bmp.getHeight());

I tried original image is 1230 x 1230, and got bitmap says is 330 x 330.
And if tried 2590 x 3849, I'll got OutOfMemoryError.

I traced it, it still throw OutOfMemoryError on line "BitmapFactory.decodeStream(is, null, options);", if original bitmap too large...

Solution 12 - Android

Above code made a little cleaner. InputStreams have finally close wrapping to ensure they get closed as well:

*Note
Input: InputStream is, int w, int h
Output: Bitmap

    try
    {
        
        final int inWidth;
        final int inHeight;
        
        final File tempFile = new File(temp, System.currentTimeMillis() + is.toString() + ".temp");
        
        {
            
            final FileOutputStream tempOut = new FileOutputStream(tempFile);
            
            StreamUtil.copyTo(is, tempOut);
            
            tempOut.close();
            
        }
        
       

        {
            
            final InputStream in = new FileInputStream(tempFile);
            final BitmapFactory.Options options = new BitmapFactory.Options();
            
            try {
                
                // decode image size (decode metadata only, not the whole image)
                options.inJustDecodeBounds = true;
                BitmapFactory.decodeStream(in, null, options);
                
            }
            finally {
                in.close();
            }
            
            // save width and height
            inWidth = options.outWidth;
            inHeight = options.outHeight;
            
        }

        final Bitmap roughBitmap;
        
        {
            
            // decode full image pre-resized
            final InputStream in = new FileInputStream(tempFile);
            
            try {
                
                final BitmapFactory.Options options = new BitmapFactory.Options();
                // calc rought re-size (this is no exact resize)
                options.inSampleSize = Math.max(inWidth/w, inHeight/h);
                // decode full image
                roughBitmap = BitmapFactory.decodeStream(in, null, options);
                
            }
            finally {
                in.close();
            }
            
            tempFile.delete();
            
        }
        
        float[] values = new float[9];
        
        {
            
            // calc exact destination size
            Matrix m = new Matrix();
            RectF inRect = new RectF(0, 0, roughBitmap.getWidth(), roughBitmap.getHeight());
            RectF outRect = new RectF(0, 0, w, h);
            m.setRectToRect(inRect, outRect, Matrix.ScaleToFit.CENTER);
            m.getValues(values);

        }
        
        // resize bitmap
        final Bitmap resizedBitmap = Bitmap.createScaledBitmap(roughBitmap, (int) (roughBitmap.getWidth() * values[0]), (int) (roughBitmap.getHeight() * values[4]), true);
        
        return resizedBitmap;
        
    }
    catch (IOException e) {
        
        logger.error("Error:" , e);
        throw new ResourceException("could not create bitmap");
        
    }

Solution 13 - Android

To scale the image the "correct" way, without skipping any pixels, you'd have to hook into the image decoder to perform the down-sampling row by row. Android (and the Skia library that underlies it) provides no such hooks, so you'd have to roll your own. Assuming you're talking jpeg images, your best bet would be to use libjpeg directly, in C.

Given the complexities involved, using the two-step subsample-then-rescale is probably best for image-preview type apps.

Solution 14 - Android

Here is an article that takes a different approach to resizing. It will attempt to load the largest possible bitmap into memory based on available memory in the process and then perform the transforms.

http://bricolsoftconsulting.com/2012/12/07/handling-large-images-on-android/

Solution 15 - Android

If you absolutely want to do one step resize you could probably load entire bitmap if android:largeHeap = true but as you can see this is not really advisable.

From docs: android:largeHeap Whether your application's processes should be created with a large Dalvik heap. This applies to all processes created for the application. It only applies to the first application loaded into a process; if you're using a shared user ID to allow multiple applications to use a process, they all must use this option consistently or they will have unpredictable results. Most apps should not need this and should instead focus on reducing their overall memory usage for improved performance. Enabling this also does not guarantee a fixed increase in available memory, because some devices are constrained by their total available memory.

Solution 16 - Android

There is a great article about this exact issue on the Android developer website: Loading Large Bitmaps Efficiently

Solution 17 - Android

This worked for me. The function gets a path to a file on the sd card and returns a Bitmap in the maximum displayable size. The code is from Ofir with some changes like image file on sd instead a Ressource and the witdth and heigth are get from the Display Object.

private Bitmap makeBitmap(String path) {

    try {
        final int IMAGE_MAX_SIZE = 1200000; // 1.2MP
        //resource = getResources();

        // Decode image size
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path, options);

        int scale = 1;
        while ((options.outWidth * options.outHeight) * (1 / Math.pow(scale, 2)) >
                IMAGE_MAX_SIZE) {
            scale++;
        }
        Log.d("TAG", "scale = " + scale + ", orig-width: " + options.outWidth + ", orig-height: " + options.outHeight);

        Bitmap pic = null;
        if (scale > 1) {
            scale--;
            // scale to max possible inSampleSize that still yields an image
            // larger than target
            options = new BitmapFactory.Options();
            options.inSampleSize = scale;
            pic = BitmapFactory.decodeFile(path, options);

            // resize to desired dimensions

            Display display = getWindowManager().getDefaultDisplay();
            Point size = new Point();
            display.getSize(size);
            int width = size.y;
            int height = size.x;

            //int height = imageView.getHeight();
            //int width = imageView.getWidth();
            Log.d("TAG", "1th scale operation dimenions - width: " + width + ", height: " + height);

            double y = Math.sqrt(IMAGE_MAX_SIZE
                    / (((double) width) / height));
            double x = (y / height) * width;

            Bitmap scaledBitmap = Bitmap.createScaledBitmap(pic, (int) x, (int) y, true);
            pic.recycle();
            pic = scaledBitmap;

            System.gc();
        } else {
            pic = BitmapFactory.decodeFile(path);
        }

        Log.d("TAG", "bitmap size - width: " +pic.getWidth() + ", height: " + pic.getHeight());
        return pic;

    } catch (Exception e) {
        Log.e("TAG", e.getMessage(),e);
        return null;
    }

}

Solution 18 - Android

Here is the code I use which doesn't have any issues decoding large images in memory on Android. I have been able to decode images larger then 20MB as long as my input parameters are around 1024x1024. You can save the returned bitmap to another file. Below this method is another method which I also use to scale images to a new bitmap. Feel free to use this code as you wish.

/*****************************************************************************
 * public decode - decode the image into a Bitmap
 * 
 * @param xyDimension
 *            - The max XY Dimension before the image is scaled down - XY =
 *            1080x1080 and Image = 2000x2000 image will be scaled down to a
 *            value equal or less then set value.
 * @param bitmapConfig
 *            - Bitmap.Config Valid values = ( Bitmap.Config.ARGB_4444,
 *            Bitmap.Config.RGB_565, Bitmap.Config.ARGB_8888 )
 * 
 * @return Bitmap - Image - a value of "null" if there is an issue decoding
 *         image dimension
 * 
 * @throws FileNotFoundException
 *             - If the image has been removed while this operation is
 *             taking place
 */
public Bitmap decode( int xyDimension, Bitmap.Config bitmapConfig ) throws FileNotFoundException
{
    // The Bitmap to return given a Uri to a file
    Bitmap bitmap = null;
    File file = null;
    FileInputStream fis = null;
    InputStream in = null;

    // Try to decode the Uri
    try
    {
        // Initialize scale to no real scaling factor
        double scale = 1;

        // Get FileInputStream to get a FileDescriptor
        file = new File( this.imageUri.getPath() );

        fis = new FileInputStream( file );
        FileDescriptor fd = fis.getFD();

        // Get a BitmapFactory Options object
        BitmapFactory.Options o = new BitmapFactory.Options();

        // Decode only the image size
        o.inJustDecodeBounds = true;
        o.inPreferredConfig = bitmapConfig;

        // Decode to get Width & Height of image only
        BitmapFactory.decodeFileDescriptor( fd, null, o );
        BitmapFactory.decodeStream( null );

        if( o.outHeight > xyDimension || o.outWidth > xyDimension )
        {
            // Change the scale if the image is larger then desired image
            // max size
            scale = Math.pow( 2, (int) Math.round( Math.log( xyDimension / (double) Math.max( o.outHeight, o.outWidth ) ) / Math.log( 0.5 ) ) );
        }

        // Decode with inSampleSize scale will either be 1 or calculated value
        o.inJustDecodeBounds = false;
        o.inSampleSize = (int) scale;

        // Decode the Uri for real with the inSampleSize
        in = new BufferedInputStream( fis );
        bitmap = BitmapFactory.decodeStream( in, null, o );
    }
    catch( OutOfMemoryError e )
    {
        Log.e( DEBUG_TAG, "decode : OutOfMemoryError" );
        e.printStackTrace();
    }
    catch( NullPointerException e )
    {
        Log.e( DEBUG_TAG, "decode : NullPointerException" );
        e.printStackTrace();
    }
    catch( RuntimeException e )
    {
        Log.e( DEBUG_TAG, "decode : RuntimeException" );
        e.printStackTrace();
    }
    catch( FileNotFoundException e )
    {
        Log.e( DEBUG_TAG, "decode : FileNotFoundException" );
        e.printStackTrace();
    }
    catch( IOException e )
    {
        Log.e( DEBUG_TAG, "decode : IOException" );
        e.printStackTrace();
    }

    // Save memory
    file = null;
    fis = null;
    in = null;

    return bitmap;

} // decode

NOTE: Methods have nothing to do with each other except createScaledBitmap calls decode method above. Note width and height can change from original image.

/*****************************************************************************
 * public createScaledBitmap - Creates a new bitmap, scaled from an existing
 * bitmap.
 * 
 * @param dstWidth
 *            - Scale the width to this dimension
 * @param dstHeight
 *            - Scale the height to this dimension
 * @param xyDimension
 *            - The max XY Dimension before the original image is scaled
 *            down - XY = 1080x1080 and Image = 2000x2000 image will be
 *            scaled down to a value equal or less then set value.
 * @param bitmapConfig
 *            - Bitmap.Config Valid values = ( Bitmap.Config.ARGB_4444,
 *            Bitmap.Config.RGB_565, Bitmap.Config.ARGB_8888 )
 * 
 * @return Bitmap - Image scaled - a value of "null" if there is an issue
 * 
 */
public Bitmap createScaledBitmap( int dstWidth, int dstHeight, int xyDimension, Bitmap.Config bitmapConfig )
{
    Bitmap scaledBitmap = null;

    try
    {
        Bitmap bitmap = this.decode( xyDimension, bitmapConfig );

        // Create an empty Bitmap which will contain the new scaled bitmap
        // This scaled bitmap should be the size we want to scale the
        // original bitmap too
        scaledBitmap = Bitmap.createBitmap( dstWidth, dstHeight, bitmapConfig );

        float ratioX = dstWidth / (float) bitmap.getWidth();
        float ratioY = dstHeight / (float) bitmap.getHeight();
        float middleX = dstWidth / 2.0f;
        float middleY = dstHeight / 2.0f;

        // Used to for scaling the image
        Matrix scaleMatrix = new Matrix();
        scaleMatrix.setScale( ratioX, ratioY, middleX, middleY );

        // Used to do the work of scaling
        Canvas canvas = new Canvas( scaledBitmap );
        canvas.setMatrix( scaleMatrix );
        canvas.drawBitmap( bitmap, middleX - bitmap.getWidth() / 2, middleY - bitmap.getHeight() / 2, new Paint( Paint.FILTER_BITMAP_FLAG ) );
    }
    catch( IllegalArgumentException e )
    {
        Log.e( DEBUG_TAG, "createScaledBitmap : IllegalArgumentException" );
        e.printStackTrace();
    }
    catch( NullPointerException e )
    {
        Log.e( DEBUG_TAG, "createScaledBitmap : NullPointerException" );
        e.printStackTrace();
    }
    catch( FileNotFoundException e )
    {
        Log.e( DEBUG_TAG, "createScaledBitmap : FileNotFoundException" );
        e.printStackTrace();
    }

    return scaledBitmap;
} // End createScaledBitmap

Solution 19 - Android

 Bitmap yourBitmap;
 Bitmap resized = Bitmap.createScaledBitmap(yourBitmap, newWidth, newHeight, true);

or:

 resized = Bitmap.createScaledBitmap(yourBitmap,(int)(yourBitmap.getWidth()*0.8), (int)(yourBitmap.getHeight()*0.8), true);

Solution 20 - Android

I use Integer.numberOfLeadingZeros to calculate the best sample size, better performance.

Full code in kotlin:

@Throws(IOException::class)
fun File.decodeBitmap(options: BitmapFactory.Options): Bitmap? {
    return inputStream().use {
        BitmapFactory.decodeStream(it, null, options)
    }
}

@Throws(IOException::class)
fun File.decodeBitmapAtLeast(
        @androidx.annotation.IntRange(from = 1) width: Int,
        @androidx.annotation.IntRange(from = 1) height: Int
): Bitmap? {
    val options = BitmapFactory.Options()

    options.inJustDecodeBounds = true
    decodeBitmap(options)

    val ow = options.outWidth
    val oh = options.outHeight

    if (ow == -1 || oh == -1) return null

    val w = ow / width
    val h = oh / height

    if (w > 1 && h > 1) {
        val p = 31 - maxOf(Integer.numberOfLeadingZeros(w), Integer.numberOfLeadingZeros(h))
        options.inSampleSize = 1 shl maxOf(0, p)
    }
    options.inJustDecodeBounds = false
    return decodeBitmap(options)
}

Solution 21 - Android

Resize the bitmap using the following code

    public static Bitmap decodeFile(File file, int reqWidth, int reqHeight){

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;        
    BitmapFactory.decodeFile(file.getPath(), options);

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

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeFile(file.getPath(), options);
   }

    private static int calculateInSampleSize(
    BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    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;
   }    

The same is also explained in the following tip/trick

http://www.codeproject.com/Tips/625810/Android-Image-Operations-Using-BitmapFactory

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionManuelView Question on Stackoverflow
Solution 1 - AndroidJustinView Answer on Stackoverflow
Solution 2 - AndroidOfirView Answer on Stackoverflow
Solution 3 - AndroidblublView Answer on Stackoverflow
Solution 4 - AndroidBostoneView Answer on Stackoverflow
Solution 5 - AndroidAlexView Answer on Stackoverflow
Solution 6 - AndroidpenduDevView Answer on Stackoverflow
Solution 7 - AndroidMojo RisinView Answer on Stackoverflow
Solution 8 - AndroidMusic MonkeyView Answer on Stackoverflow
Solution 9 - AndroidcybergenView Answer on Stackoverflow
Solution 10 - AndroidAndrey ChorniyView Answer on Stackoverflow
Solution 11 - AndroidRRTWView Answer on Stackoverflow
Solution 12 - Androiduser1327738View Answer on Stackoverflow
Solution 13 - AndroidD0SBootsView Answer on Stackoverflow
Solution 14 - AndroidTheoView Answer on Stackoverflow
Solution 15 - AndroidIgor ČordašView Answer on Stackoverflow
Solution 16 - AndroidMuzikantView Answer on Stackoverflow
Solution 17 - AndroidPentaView Answer on Stackoverflow
Solution 18 - Androiduser560663View Answer on Stackoverflow
Solution 19 - AndroidVaishali SutariyaView Answer on Stackoverflow
Solution 20 - Androiduser4003256View Answer on Stackoverflow
Solution 21 - AndroidAmolView Answer on Stackoverflow