有效地加载大位图文件-Loading Large Bitmaps Efficiently

图像有各种不同的形状和大小。在许多情况下,他们往往比一个典型应用程序的用户界面(UI)所需要的资源更大。例如,系统的Gallery程序展示使用Android设备的照相机所拍摄的照片通常要比你的设备的屏幕密度的分辨率更高。
既然你所使用的内存有限,理想状况下你只想在内存中加载一个低分辨率的版本。低分辨率的方案应该匹配显示它的UI组件的大小。一个更高分辨率的图片不提供任何可见的好处,但是由于额外的缩放会导致额外的性能开销,仍然占用缩放之前的内存,。
这节课将引导你在不超过内存限制的情况下通过解码大型位图,在内存中加载一个较小的位图子样本。
读取一个位图的尺寸和类型-Read Bitmap Dimensions and Type

为了从多种资源来创建一个位图,BitmapFactory类提供了几个解码的方法(decodeByteArray(),decodeFile(),decodeResource(),等等)。根据你的图像数据资源选择最合适的解码方法。这些方法试图请求分配内存来构造位图,因此很容易导致OutOfMemory异常。每种类型的解码方法都有额外的特征可以让你通过BitMapFactory.Options类指定解码选项。当解码时避免内存分配可以设置inJustDecodeBounds属性为true,位图对象返回null但是设置了outWidth,outHeight和outMimeType。这种技术允许你在创建位图(和分配内存)之前去读取图像的尺寸和类型。

BitmapFactory.Options options = new BitmapFactory.Options();

options.inJustDecodeBounds = true;

BitmapFactory.decodeResource(getResources(), R.id.myimage, options);

int imageHeight = options.outHeight;

int imageWidth = options.outWidth;

String imageType = options.outMimeType;

为了避免java.lang.OutOfMemory异常,在解码位图之前请检查它的尺寸,除非你十分确定资源提供给你的可预见的图像数据正好满足你的内存。
加载一个缩小版本到内存中(Load a Scaled Down Version into Memory)

现在的图像尺寸都是已知的,他们可以被用来决定是否应该加载完整的图片到内存或者是否用一个缩小的版本去代替加载。以下是一些值得考虑的因素:
估计加载完整图像所需要的内存;
你承诺加载这个图片所需空间带给你的程序的其他内存需求;
准备加载图像的目标ImageView或UI组件尺寸;
当前设备的屏幕尺寸和密度;
例如,如果1024*768像素的图像最终被缩略地显示在一个128*96像素的ImageView中,就不值得加载到内存中去。
告诉解码器去重新采样这个图像,加载一个更小的版本到内存中,在你的BitmapFactory.Option对象中设置inSampleSize为true。例如,将一个分辨率为2048*1536的图像用 inSampleSize值为4去编码将产生一个大小为大约512*384的位图。加载这个到内存中仅使用0.75MB,而不是完整的12MB大小的图像(假设使用ARGB_8888位图的配置)。这里有一个方法在目标的宽度和高度的基础上来计算一个SampleSize的值。

  public static int calculateInSampleSize(

  BitmapFactory.Options options, int reqWidth, int reqHeight) {

  // Raw height and width of image

  final int height = options.outHeight;

  final int width = options.outWidth;

  int inSampleSize = 1;

  if (height > reqHeight || width > reqWidth) {

  if (width > height) {

  inSampleSize = Math.round((float)height / (float)reqHeight);

  } else {

  inSampleSize = Math.round((float)width / (float)reqWidth);

  }

  }

  return inSampleSize;

  }

NOTE:使用2的幂数设置inSampleSize的值可以使解码器更快,更有效。然而,如果你想在内存或硬盘中缓存一个图片调整后的版本,通常解码到合适的图像尺寸更适合来节省空间。
要使用这种方法,首先解码,将inJustDecodeBounds设置为true,将选项传递进去,然后再次解码,在使用新的inSampleSize值并将inJustDecodeBounds设置为false:

  public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,

  int reqWidth, int reqHeight) {

  // First decode with inJustDecodeBounds=true to check dimensions

  final BitmapFactory.Options options = new BitmapFactory.Options();

  options.inJustDecodeBounds = true;

  BitmapFactory.decodeResource(res, resId, options);

  // Calculate inSampleSize

  options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

  // Decode bitmap with inSampleSize set

  options.inJustDecodeBounds = false;

  return BitmapFactory.decodeResource(res, resId, options);

  }

这种方法可以很容易地加载任意大小的位图到一个ImageView显示一个100x100像素的缩略图,如下面的示例代码所示:

mImageView.setImageBitmap(

decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));
你可以按照类似的过程,用适当的BitmapFactory.decode*中的方法去解码一个从其他资源得到的位图

Loading Large Bitmaps Efficiently的更多相关文章

  1. Displaying Bitmaps Efficiently 显示图片相关

    http://developer.android.com/training/displaying-bitmaps/index.html .手机内存资源有限 .Bitmap占用的内存大 .App有时需要 ...

  2. trying to draw too large(106,975,232 bytes) bitmap.

    Loading Large Bitmaps Efficiently This lesson teaches you to Read Bitmap Dimensions and Type Load a ...

  3. [译]Android调整图像大小的一些方法

    翻译自 某大神在Stack Overflow里的自问自答 (一般我们将Bitmap翻译为位图,但为了更好理解,在本文中我将它翻译成图像): 我们在开发的时候,经常需要从服务器中加载图像到客户端中,但有 ...

  4. [原] Android持续优化 - 提高流畅度

    一.形象的感官一下流畅度概念 1. 这是官方给出的概念:Android流畅运行,需要运行60帧/秒, 则需要每帧的处理时间不超过16ms. 2. 每秒帧数,实际上就是指动画或视频每秒放映的画面数.因此 ...

  5. 学习笔记 - 深究Bitmap压缩避免OOM的核心inSampleSize的最佳取值

    /** * 测试代码,通过在SDCard根目录放置几种不同大小的图片, 来自动测试压缩方式是否有效同时看是否会内存不够. * * @since * By:AsionTang * At:2014年3月2 ...

  6. android 高效显示Bitmap - 开发文档翻译

    由于本人英文能力实在有限,不足之初敬请谅解 本博客只要没有注明“转”,那么均为原创,转贴请注明本博客链接链接 Displaying Bitmaps Efficiently 高效显示Bitmap Lea ...

  7. Android Training

    Building Apps with Content Sharing Simple Data --> Intent && ActionProvider 介绍如何让应用程序共享简单 ...

  8. Android训练课程(Android Training) - 高效的显示图片

    高效的显示图片(Displaying BitmapsEfficiently) 了解如何使用通用的技术来处理和读取位图对象,让您的用户界面(UI)组件是可响应的,并避免超过你的应用程序内存限制的方式.如 ...

  9. 【Android】自己定义圆形ImageView(圆形头像 可指定大小)

    近期在仿手Q的UI,这里面常常要用到的就是圆形头像,看到 在android中画圆形图片的几种办法 这篇文章,了解了制作这样的头像的原理.只是里面提供的方法另一个不足的地方就是不能依据实际需求改变图片的 ...

随机推荐

  1. 关于nginx做代理,uwsgi gunicorn等服务器做后端时

    (1) 响应数据过大 被截断的问题 通常看buffers参数的设置(缓冲从后端服务器的应答) uwsgi的参数是 uwsgi_buffers 4 128k gunicorn 设置代理参数 proxy_ ...

  2. 2017-2018-1 20179215 第十一周 ShellShock攻击实验

    <Linux内核原理与设计>第十一周作业 ShellShock攻击实验 分组:和20179205王雅哲共同完成实验及博客攥写 实验内容:  Bash中发现了一个严重漏洞shellshock ...

  3. DCOS安装

    安装pre-flight master机器会安装上安装文件(同时check条件是否满足要求),其他的agent设备只是check各种条件是否具备. 确保53/2181端口没有被占用:centos7每次 ...

  4. [转载]centos下yum安装samba及配置

    centos下yum安装samba及配置 在我们使用 Windows 作为客户机的时候,通常有文件.打印共享的需求.作为Windows 网络功能之一,通常可以在 Windows 客户机之间通过Wind ...

  5. 聊聊 SQL Joins

    SQL 中的 Join 有以下几种类型: 1.Cross Join 交叉连接,没有条件筛选,返回笛卡尔积. 如果以 ,(逗号)分隔表名进行查询如 select * from tbl_name1, tb ...

  6. SpringBoot自动化配置之三:深入SpringBoot:自定义EnableAutoConfiguration

    前言 上面几篇文章介绍了SpringFramework的一些原理,这里开始介绍一下SpringBoot,并通过自定义一些功能来介绍SpringBoot的原理.SpringBoot在SpringFram ...

  7. react过渡动画效果的实现,react-transition-group

    本文介绍react相关的过渡动画效果的实现 有点类似vue的transition组件,主要用于组件mount和unmount之前切换时应用动画效果 安装 cnpm install react-tran ...

  8. 第十章 Executor框架

    在Java中,使用线程来异步执行任务.Java线程的创建与销毁需要一定的开销,如果我们为每一个任务创建一个新线程来执行,这些线程的创建与销毁将消耗大量的计算资源.同时,为每一个任务创建一个新线程来执行 ...

  9. 部署和调优 1.1 nfs部署和优化-1

    NFS服务会经常用到,用于在网络上共享存储.举一个例子来说明一下 NFS .假如有三台机器 A.B.C,它们需要访问同一个目录,目录中都是图片,传统的做法是把这些图片分别放到 A.B.C.但是,若使用 ...

  10. 【转载】基于TINY4412的Andorid开发-------简单的LED灯控制

    阅读目录(Content) 一.编写驱动程序 二.编写代码测试驱动程序 三.编写HAL代码 四.编写Framework代码 五.编写JNI代码 六.编写App 参考资料: <Andriod系统源 ...