Android开发艺术探索,Bitmap获取缩略图

日期:2019-09-07编辑作者:编程应用

前言

追思了下此前写的调用相机和相册的机能,准备把它们构成下,想起已经用Motorola在赢得大图时OOM的主题素材,决定重看三回当初的化解措施。在获取缩略图步骤上发掘了系统现已提供了工具类ThumbnailUtils,当然收缩内部存款和储蓄器消耗不止这一步。

  1. BitmapFactory类提供各样艺术:decodeFile、decodeResource、decodeStream和decodeByteArray;个中decodeFile和decodeResource直接的调用了decodeStream方法;这多个章程最终在Android底层达成。
  2. 怎么着急速的加载Bitmap?大旨境想:按需加载;比非常多时候ImageView并从未原来图片那么大,所以没须要加载原始大小的图纸。选取BitmapFactory.Options来加载所需尺寸的图样。 通过BitmapFactory.Options来缩放图片,首如若用到了它的inSampleSize参数,即采集样品率。 in萨姆pleSize应为2的指数,要是否系统会向下取整并精选三个最周边2的指数来代替;缩放比例为1/(inSampleSize的一遍方)。
  3. Bitmap内部存储器占用:拿一张10241024像素的图纸来讲,假定接纳A奥迪Q5GB8888格式存款和储蓄,那么它占用的内部存款和储蓄器为10241024*4,即4MB。
  4. 缩放图片

原先获得缩略图的措施

public static Bitmap getThumbnail(Uri uri,int size, Context context) throws Exception { InputStream input = context.getContentResolver().openInputStream; //配置BitmapFactory.Options,inJustDecodeBounds设为true,以获取图片的宽高 BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options(); onlyBoundsOptions.inJustDecodeBounds = true; onlyBoundsOptions.inDither=true;//optional onlyBoundsOptions.inPreferredConfig=Bitmap.Config.ARGB_8888;//optional //计算inSampleSize缩放比例 BitmapFactory.decodeStream(input, null, onlyBoundsOptions); input.close(); if ((onlyBoundsOptions.outWidth == -1) || (onlyBoundsOptions.outHeight == -1)) return null; int originalSize = (onlyBoundsOptions.outHeight > onlyBoundsOptions.outWidth) ? onlyBoundsOptions.outHeight : onlyBoundsOptions.outWidth; double ratio = (originalSize > size) ? (originalSize / size) : 1.0; //获取到缩放比例后,再次设置BitmapFactory.Options,获取图片缩略图 BitmapFactory.Options bitmapOptions = new BitmapFactory.Options(); bitmapOptions.inSampleSize = getPowerOfTwoForSampleRatio; bitmapOptions.inDither=true;//optional bitmapOptions.inPreferredConfig=Bitmap.Config.ARGB_8888;//optional input = context.getContentResolver().openInputStream; Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions); input.close(); return bitmap;}/** * 将double的比例采用近似值的方式转为int * @param ratio * @return */private static int getPowerOfTwoForSampleRatio(double ratio){ int k = Integer.highestOneBitMath.floor; if return 1; else return k;}

全体挂念是通过设置BitmapFactory.Options.inJustDecodeBounds设为true,先获得到图片的宽高而并不会生产Bitmap;再通过所需图片的最长边size来博取缩放比例inSampleSize的值;然后获所需尺寸的图形。

收获缩放比例inSampleSize值的算法能够单独拉出三个办法,依据须求举办安装:

/** * 根据图片的Options和期望的图片大小来获取图片的缩小比例、 * 如果图片的宽或高有一个大于目标值,就做处理;否则不做处理。 * 关于inSampleSize需要注意,它只能是2的次方,否则它会取最接近2的次方的值。 * @param options 目标图片的BitmapFactory.Options * @param expectationWidth 期望图片的宽 * @param expectationHeight 期望图片的高 * @return */public static int sampleSize(BitmapFactory.Options options, int expectationWidth, int expectationHeight) { //首先获取图片的宽 int rawWidth = options.outWidth; int rawHeight = options.outHeight; //在计算图片的sampleSize int inSampleSize = 0; if (rawHeight > expectationHeight || rawWidth > expectationWidth) { float ratioHeight = rawHeight / expectationHeight; float rationWidth = rawWidth / expectationWidth; inSampleSize =  Math.min(ratioHeight, rationWidth); } inSampleSize = Math.max(inSampleSize, 1); return inSampleSize ;}

这种缩放是思考短的边进行缩放调节,假诺短边长度小于期望长度,不开展缩放。

透过上述措施成功博获得图片缩略图,但系统现已给大家提供获取格局,并且算法上思考的场所更不错,上边来探视。

ThumbnailUtils

获取图片缩略图,大家采纳的办法是extractThumbnail,但关键达成方式是transform.我的是API23的源码。

 /** * Transform source Bitmap to targeted width and height. */private static Bitmap transform(Matrix scaler, Bitmap source, int targetWidth, int targetHeight, int options) { //是否可以进行图片放大操作 boolean scaleUp = (options & OPTIONS_SCALE_UP) != 0; //是否可以进行原图资源回收操作 boolean recycle = (options & OPTIONS_RECYCLE_INPUT) != 0; int deltaX = source.getWidth() - targetWidth; int deltaY = source.getHeight() - targetHeight; /* *图片如果小于目标值,进行放大处理 */ if (!scaleUp && (deltaX < 0 || deltaY < 0)) { /* * In this case the bitmap is smaller, at least in one dimension, * than the target. Transform it by placing as much of the image * as possible into the target and leaving the top/bottom or * left/right  black. */ Bitmap b2 = Bitmap.createBitmap(targetWidth, targetHeight, Bitmap.Config.ARGB_8888); Canvas c = new Canvas; int deltaXHalf = Math.max(0, deltaX / 2); int deltaYHalf = Math.max(0, deltaY / 2); Rect src = new Rect( deltaXHalf, deltaYHalf, deltaXHalf + Math.min(targetWidth, source.getWidth, deltaYHalf + Math.min(targetHeight, source.getHeight; int dstX = (targetWidth - src.width / 2; int dstY = (targetHeight - src.height / 2; Rect dst = new Rect( dstX, dstY, targetWidth - dstX, targetHeight - dstY); c.drawBitmap(source, src, dst, null); if  { source.recycle(); } c.setBitmap; return b2; } /* *图片如果大于目标值,进行缩小处理 */ float bitmapWidthF = source.getWidth(); float bitmapHeightF = source.getHeight(); float bitmapAspect = bitmapWidthF / bitmapHeightF; float viewAspect =  targetWidth / targetHeight; //获取缩放比例,如果原图宽高比大于目标宽高比,也就是原图变得更“窄”了 //就用高度比例进行缩放,否则用宽度比例进行缩放。 //效果上看就是将图片完全展示。 if (bitmapAspect > viewAspect) { float scale = targetHeight / bitmapHeightF; if (scale < .9F || scale > 1F) { scaler.setScale(scale, scale); } else { scaler = null; } } else { float scale = targetWidth / bitmapWidthF; if (scale < .9F || scale > 1F) { scaler.setScale(scale, scale); } else { scaler = null; } } //根据缩放比例创建缩略图 Bitmap b1; if (scaler != null) { // this is used for minithumb and crop, so we want to filter here. b1 = Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), scaler, true); } else { b1 = source; } if (recycle && b1 != source) { source.recycle(); } int dx1 = Math.max(0, b1.getWidth() - targetWidth); int dy1 = Math.max(0, b1.getHeight() - targetHeight); Bitmap b2 = Bitmap.createBitmap( b1, dx1 / 2, dy1 / 2, targetWidth, targetHeight); if  { if (recycle || b1 != source) { b1.recycle(); } } return b2;}

能够看来,系统在效率上看就是将图纸完全展示,算法上思索的状态也尤为丰硕。原图的回收,是否推广,目的图片的宽高端思虑进来了。

 public static Bitmap decodeBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) { BitmapFactory.Options options = new BitmapFactory.Options(); //1. 将BitmapFactory.Options的inJustDecodeBounds参数设置为true并加载图片。 options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options); //2. 根据采样率的规则并结合目标View的所需大小计算出采样率inSampleSize。 options.inSampleSize = calcuateInSampleSize(options, reqWidth, reqHeight); //3. 将BitmapFactory.Options的inJustDecodeBounds参数设置为false,然后重新加载图片。 options.inJustDecodeBounds = false; return BitmapFactory.decodeResource(res, resId, options); } //获取采样率 private static int calcuateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { int width = options.outWidth; int height = options.outHeight; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { int halfHeight = height / 2; int halfWidth = width / 2; while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) { inSampleSize *= 2; } } return inSampleSize; }// 显示图片Bitmap bitmap = DecodeBitmap.decodeBitmapFromResource(getResources(), R.mipmap.haimei2, 400, 400);imageView.setImageBitmap;

总结

收获缩略图总的步骤就是:

graph TBA{开始}-->BB --> C[根据算法获取缩放比例]C --> D[根据缩放比例创建缩略图]

ThumbnailUtils的行数只有521行,还有个别方法并有被运用到,感兴趣的能够去探问。即使ThumbnailUtils的代码不长,但学到了差异的完成方式和小说形式,驾驭了温馨的阙如。多看源码对团结的升级换代照旧很有用的。

当inJustDecodeBounds参数为true时,BitmapFactory只会剖析图片的原始宽/高新闻,并不会真的的加载图片。必要留意那时候BitmapFactory获取的图片宽/高新闻和图纸的任务与程序运转的配备有关。

  1. 哪些收缩流量消耗?缓存。当程序第一回从网络上加载图片后,将其缓存在存款和储蓄设备中,下一次应用那张图片的时候就毫无再从互连网从获得了。一般情状会把图片存一份到内部存款和储蓄器中,一份到存款和储蓄设备中,若是内部存款和储蓄器中没找到就去存款和储蓄设备中找,还未有找到就从网络上下载。
  2. 方今常用的缓存算法是LRU,是近年最少使用算法,当缓存满时,优先淘汰这一个近日至少使用的缓存对象。接纳LRU算法的缓存有三种:LRUCache和DiskLruCache。
  3. LruCache是Android3.1所提供的几个缓存类,通过support-v4包容包能够合营到先前时代的Android版本。LruCache是三个泛型类,是线程安全的,内部使用LinkedHashMap以强引用的不二等秘书技存款和储蓄外界缓存对象,并提供get和put方法来产生缓存的获得和增多操作,当缓存满时,LruCache会移除较早的行使的缓存对象。LruCache初阶化时需重写sizeOf主意,用于计算缓存对象的轻重。
  • 强引用:直接的靶子援引
  • 软引用:当三个对象仅有软引用存在的时候,系统内部存储器不足的时此对象会被GC回收。
  • 弱引用 : 当三个对象独有弱援用存在的时候,此目的随时会被GC回收。
  1. DiskLruCache用来落到实处磁盘缓存,DiskLruCache获得了Android官方文书档案推荐,但它不属于Android SDK的一有的源码在此地
  2. 本人完成叁个ImageLoader,满含
  3. 图表压缩功效
  4. 内部存款和储蓄器缓存和磁盘缓存
  5. 二只加载和异步加载的接口设计

详见请看主席的随书源码

  1. 兑现Instagram效果,如若图片都亟需是星型;那样做不慢,自定义叁个ImageView,重写onMeasure方法。
 @Override protected void onMeasure(int widthMeasureSpec,int heightMeasureSpec){ super.onMeasure(widthMeasureSpec,widthMeasureSpec); }
  1. 优化列表卡顿现象
  2. 绝不在getView中推行耗费时间操作,不要在getView中平昔加载图片。
  3. 决定异步职务的实行功效:借使顾客特意频仍上下滑动,getView方法会不停调用,进而发出大批量的异步任务。能够虚拟在列表滑动截至加载图片;给ListView可能GridView设置setOnScrollListener并在OnScrollListener的onScrollStateChanged方法中推断列表是不是处在滑动状态,假使是的话就终止加载图片。
  4. 繁多地方下,能够使用硬件加快化解莫名卡顿难点,通过设置android:hardwareAccelerated="true"就能够为Activity开启硬件加快。

本文由今晚最快开奖现场直播发布于编程应用,转载请注明出处:Android开发艺术探索,Bitmap获取缩略图

关键词:

热修复热点框架简析,Android插件框架机制研商

笔者 百度任玉刚 插件化框架 途牛已上线使用帮衬代码能源文件以插件情势加入到host。 插件化的主干形式是将二个...

详细>>

阅读笔记,线程安全性

首先使代码正确运行,然后再提高代码速度。【正确编写并发程序的方法】 线程安全:当多个线程访问某个类(对象...

详细>>

Android开辟方式探求,Bitmap的加载和Cache

BitmapFactory 类提供四种方法:decodeFile、decodeResource、decodeStream和decodeByteArray;其中decodeFile和decodeResource间接的调用了...

详细>>

读书笔记

RemoteViews是一种远程View,能够在别的进程中显得,为了能够更新它的分界面,RemoteViews提供了一组基础操成效于跨进度...

详细>>