我有一个图像密集型的 Android 应用程序。我目前正在使用Bitmap.createScaledBitmap() http://developer.android.com/reference/android/graphics/Bitmap.html#createScaledBitmap%28android.graphics.Bitmap,%20int,%20int,%20boolean%29将图像缩放至所需尺寸。但是,此方法要求内存中已有原始位图,该位图可能相当大。
如何缩放正在下载的位图,而不先将整个位图写入本地内存或文件系统?
此方法将从图像中读取标头信息以确定其大小,然后读取图像并将其缩放到所需的大小,而不为完整的原始大小图像分配内存。
它还使用BitmapFactory.Options.inPurgeable http://developer.android.com/intl/fr/reference/android/graphics/BitmapFactory.Options.html#inPurgeable,这似乎是一个记录很少但在使用大量位图时防止 OoM 异常的理想选择。更新:不再使用 inPurgeable,请参阅这张纸条 https://stackoverflow.com/questions/7068132/why-would-i-ever-not-use-bitmapfactorys-inpurgeable-option/7068403#7068403来自罗曼
它的工作原理是使用 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 ) {}
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)