Этот метод считывает информацию заголовка с изображения, чтобы определить его размер, затем считывает изображение и масштабирует его до нужного размера на месте, не выделяя память для полного исходного размера изображения.
Он также использует BitmapFactory.Options.inPurgeable , который представляется редко документированным, но желательным вариантом для предотвращения исключений OoM при использовании большого количества растровых изображений. ОБНОВЛЕНИЕ: больше не использует inPurgeable, см. эту заметку от Romain
Он работает с использованием BufferedInputStream для считывания информации заголовка для изображения перед считыванием всего изображения через InputStream.
/**
* Read the image from the stream and create a bitmap scaled to the desired
* size. Resulting bitmap will be at least as large as the
* desired minimum specified dimensions and will keep the image proportions
* correct during scaling.
*/
protected Bitmap createScaledBitmapFromStream( InputStream s, int minimumDesiredBitmapWith, int minimumDesiredBitmapHeight ) {
final BufferedInputStream is = new BufferedInputStream(s, 32*1024);
try {
final Options decodeBitmapOptions = new Options();
// For further memory savings, you may want to consider using this option
// decodeBitmapOptions.inPreferredConfig = Config.RGB_565; // Uses 2-bytes instead of default 4 per pixel
if( minimumDesiredBitmapWidth >0 && minimumDesiredBitmapHeight >0 ) {
final Options decodeBoundsOptions = new Options();
decodeBoundsOptions.inJustDecodeBounds = true;
is.mark(32*1024); // 32k is probably overkill, but 8k is insufficient for some jpgs
BitmapFactory.decodeStream(is,null,decodeBoundsOptions);
is.reset();
final int originalWidth = decodeBoundsOptions.outWidth;
final int originalHeight = decodeBoundsOptions.outHeight;
// inSampleSize prefers multiples of 2, but we prefer to prioritize memory savings
decodeBitmapOptions.inSampleSize= Math.max(1,Math.min(originalWidth / minimumDesiredBitmapWidth, originalHeight / minimumDesiredBitmapHeight));
}
return BitmapFactory.decodeStream(is,null,decodeBitmapOptions);
} catch( IOException e ) {
throw new RuntimeException(e); // this shouldn't happen
} finally {
try {
is.close();
} catch( IOException ignored ) {}
}
}