Android异步加载全解析之Bitmap
Android异步加载全解析之Bitmap
在这篇文章中,我们分析了Android在对大图处理时的一些策略——Android异步加载全解析之大图处理 戳我戳我
那么在这篇中,我们来对图像——Bitmap进行一个更加细致的分析,掌握Bitmap的点点滴滴。
引入
Bitmap内存
Android异步加载全解析之大图处理
Android异步加载全解析之引入缓存
SoftReference和BitmapFactory.Options.inBitmap参数
1、重用的Bitmap和即将被解码的Bitmap必须是相同的尺寸,且是JPEG或者PNG格式的。
2、 BitmapFactory.Options.inPreferredConfig字段设置无效,因为会被重用的Bitmap的configuration所覆盖。
3、一定要使用解码方法返回的Bitmap,因为重用可能会失败。
另外,在Android 3.0 (API Level 11),及以上的版本中,当Bitmap被从LruCache中挤出时,我们可以把这个Bitmap的soft reference存起来当作以后解码时的inBitmap来使用。
URL url = new URL(urlString); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); is = new BufferedInputStream(conn.getInputStream()); bitmap = BitmapFactory.decodeStream(is);
其实,系统还给我们提供了一个更加高效的方法——decodeFileDescriptor,它为啥高效呢,其实是一个历史原因,大家都知道,C比Java略快,所以,decodeFileDescriptor比decodeStream略快,就是因为decodeFileDescriptor在源码中是使用底层库来解析的,例如:
FileInputStream is = = new FileInputStream(path); bmp = BitmapFactory.decodeFileDescriptor(is.getFD(), null, opts);因此,在调用DiskLruCache来使用的时候,这个方法就可以比decodeFile更快。这里我们也提供一个完整的调用代码:
public static OutputStream decodeBitmap(String path) { BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inJustDecodeBounds = true;// 设置成了true,不占用内存,只获取bitmap宽高 BitmapFactory.decodeFile(path, opts); opts.inSampleSize = computeSampleSize(opts, -1, 1024 * 800); opts.inJustDecodeBounds = false;// 这里一定要将其设置回false,因为之前我们将其设置成了true opts.inPurgeable = true; opts.inInputShareable = true; opts.inDither = false; opts.inPurgeable = true; opts.inTempStorage = new byte[16 * 1024]; FileInputStream is = null; Bitmap bmp = null; InputStream ins = null; ByteArrayOutputStream baos = null; try { is = new FileInputStream(path); bmp = BitmapFactory.decodeFileDescriptor(is.getFD(), null, opts); double scale = getScaling(opts.outWidth * opts.outHeight, 1024 * 600); Bitmap bmp2 = Bitmap.createScaledBitmap(bmp, (int) (opts.outWidth * scale), (int) (opts.outHeight * scale), true); bmp.recycle(); baos = new ByteArrayOutputStream(); bmp2.compress(Bitmap.CompressFormat.JPEG, 100, baos); bmp2.recycle(); return baos; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); ins.close(); baos.close(); } catch (IOException e) { e.printStackTrace(); } System.gc(); } return baos; } private static double getScaling(int src, int des) { /** * 目标尺寸÷原尺寸 sqrt开方,得出宽高百分比 */ double scale = Math.sqrt((double) des / (double) src); return scale; }
Bitmap二次采样技术
Bitmap图像压缩
大小压缩
质量压缩
private Bitmap compressImage(Bitmap bitmap) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); //质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中 bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos); int options = 100; //循环判断如果压缩后图片是否大于100kb,大于继续压缩 while (baos.toByteArray().length / 1024 > 100) { //重置baos即清空baos baos.reset(); //这里压缩options%,把压缩后的数据存放到baos中 bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos); //每次都减少10 options -= 10; } //把压缩后的数据baos存放到ByteArrayInputStream中 ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray()); //把ByteArrayInputStream数据生成图片 Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null); return bitmap; }
我的Github
我的视频 慕课网
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。