Aqui está o código que uso, sem problemas na decodificação de imagens grandes na memória do Android. Consegui decodificar imagens maiores que 20 MB, desde que meus parâmetros de entrada estejam em torno de 1024x1024. Você pode salvar o bitmap retornado em outro arquivo. Abaixo desse método, há outro método que também uso para dimensionar imagens para um novo bitmap. Sinta-se livre para usar este código como desejar.
/*****************************************************************************
* 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
NOTA: Os métodos não têm nada a ver um com o outro, exceto o método createScaledBitmap chama o método de decodificação acima. Observe que a largura e a altura podem mudar da imagem original.
/*****************************************************************************
* 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