高效加载大的图片

Loading Large Bitmaps Efficiently 高效的加载大图

图片可能以各种各样的形状,尺寸展现出来,大多数情况下它们的展现方式,是超出一般应用程序的UI需求的。举例来说,系统的”相册”应用中展现的图片(Android设备拍摄的相片)是超过你的设备屏幕的分辨率的。

假设你在一个内存有限的环境下工作,理想情况下你只需要加载一个低分辨率的版本进入内存。相对较低的分辨率的图片应该匹配UI组件的需求,并且将它们显示出来。 在这种情况下(需求的分辨率不需要很高),一张高分辨率的图片不会在视觉上给人更好的感受,因为你显示的效果不需要那么好。但是这张图片会占用很多内存,当你在快速缩放的时候它会给视觉显示任务带来负担。

这篇文章将教会你 在解析高分辨率图片的时候 通过 处理将其变为相对低一点的分辨率的图片然后加载进内存,这样就不会超出每个应用程序的内存限制了。

Read Bitmap Dimensions and Type 获取图片的尺寸和类型

BitmapFactory这个类提供了几种解析图片的方法 (decodeByteArray(), decodeFile(), decodeResource() )用来从不同的数据源创建一个Bitmap对象。 基于你的数据源,来选择合适的方法。

这些方法在执行过程中会为已经创建的bitmap分配内存,所以会很容易的出现OOM(内存溢出)异常。

每一个方法都会自己的特征让你来区分它们。通过 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;

为了避免OOM异常,你必须在加载和解析图片的时候检查一下尺寸,除非你很清楚的知道你要加载的图片是在合理的内存范围之内的。

Load a Scaled Down Version into Memory 加载一个缩放的图片进入内存

现在我们已经知道了图片的尺寸,它们可以用来加载(或者缩放之后)进入内存了,以下这些因素是你要考虑的。

  • 当你加载一整张图片进入内存的时候,你必须估算一下内存的消耗。
  • 包括了应用的其他内存消耗之后,你可以给你当前要加载的图片分配多少内存。
  • 用来显示图片的 目标控件(ImageView,或者UI组件)的尺寸。
  • 当前设备的屏幕尺寸和分辨率。

举例来说,当你要 将一个1024x768像素的图片显示在 128x96像素的ImageView上的时候是非常浪费的。

在 BitmapFactory.Options 对象中设置 inSampleSize 为 true,就可以在解析图片的时候,加载一个缩小的图片进入内存。 举例来说 如果你把 inSampleSize的值设置为4的话,一张 2048x1536分辨率的图片就可以被处理为 大约512x384分辨率的bitmap。那么原先一张加载入内存需要12M的图片就仅仅用了0.75M(假设bitmap是ARGB_8888).

下面有一个方法用来计算 缩放比例的值,根据你的图片尺寸和要求的尺寸。

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) {

    final int halfHeight = height / 2;
    final int halfWidth = width / 2;

    // Calculate the largest inSampleSize value that is a power of 2 and keeps both
    // height and width larger than the requested height and width.
    while ((halfHeight / inSampleSize) > reqHeight
            && (halfWidth / inSampleSize) > reqWidth) {
        inSampleSize *= 2;
    }
  }

  return inSampleSize;
}

注意:Note: A power of two value is calculated because the decoder uses a final value by rounding down to the nearest power of two, as per the inSampleSize documentation.

这句话目前不知道怎么翻译

用下面这个方法解析一张图片的时候 首先将 inJustDecodeBounds 设置为 true,计算出inSampleSize并且设置options的inSampleSize 然后将inJustDecodeBounds 设置为false;

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
    int reqWidth, int reqHeight) {

// First decode with inJustDecodeBounds=true to check dimensions
//第一次 先将 inJustDecodeBounds=true  查看尺寸,计算inSampleSize的值。
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);

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

//计算完了之后 设置为 false
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);

}

下面这个方法可以很简单的让一张超过ImageView尺寸的图片以缩略图的形式显示出来。

mImageView.setImageBitmap(decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));

你也可以模仿这个过程,定制一些 别的方法 BitmapFactory.decode*。

时间: 2024-10-10 14:57:16

高效加载大的图片的相关文章

Android 高效加载大图片避免OOM

参考链接:http://blog.csdn.net/coderinchina/article/details/40964205 我们项目中经常会加载图片,有时候如果加载图片过多的话,小则导致程序很卡,重则OOM导致App挂了,今天翻译https://developer.android.com/training/displaying-bitmaps/index.html,学习Google高效加载大图片的方法. 图片有各种形状和大小,但在大多数情况下,这些图片都会大于我们程序所需要的大小.比如说系统

(四十二)、加载大分辨率图片到内存

有些图片的分辨率比较高,把它直接加载到手机内存中之后,会导致堆内存溢出的问题,下面就讲解一下Android的堆内存以及如何在Android应用中加载一个高分辨率的图片的方法. 1  还原堆内存溢出的错误首先来还原一下堆内存溢出的错误.首先在SD卡上放一张照片,分辨率为(3776 X 2520),大小为3.88MB,是我自己用相机拍的一张照片.应用的布局很简单,一个Button一个ImageView,然后按照常规的方式,使用BitmapFactory加载一张照片并使用一个ImageView展示.代

Android开发之加载大分辨率图片

Android中图片占用内存的大小=图片的总像数*每个像数占用的大小. Android保存图片像素信息使用ARGB,意思是每个像素占用4个字节. 以分辨率为2400*3200的图片来说,加载到Android需要2400*3200*4=30720000字节,需要30000Kb,需要29.30Mb 直接把这个分辨率的图片加载到内存中,很容易OOM. 解决方法:把图片的分辨率缩放到手机屏幕的分辨率大小,这样就不会出现OOM 1.通过getWindowManager().getDefaultDispla

高效加载本地相册图片的ImageLoader类

当我们相册中的图片有几千张的时候,你快速的拖动滚动条到底部,怎么样才能保证图片加载的流畅性以及避免OOM呢 1.使用Lru算法对图片进行缓存保证流畅性以及避免OOM 2.图片加载肯定是要异步进行的,那么就涉及到多线程的并发进行,使用线程池对任务进行调度 3.使用android内部的异步消息机制Looper+Handler对taskQueue进行轮询执行 1.图片加载器,task任务列频繁调用,所以要做成单例模式,编写一个单例的ImageLoader类,并声明必要的成员变量 /** * @auth

Android_优化查询加载大数量的本地相册图片

一.概述 讲解优化查询相册图片之前,我们先来看下PM提出的需求,PM的需求很简单,就是要做一个类似微信的本地相册图片查询控件,主要包含两个两部分: 进入图片选择页面就要显示出手机中所有的照片,包括系统相册图片和其他目录下的所有图片,并按照时间倒叙排列 切换相册功能,切换相册页面列出手机中所有的图片目录列表,并且显示出每个目录下所有的图片个数以及封面图片 这两个需求看似简单,实则隐藏着一系列的性能优化问题.在做优化之前,我们调研了一些其他比较出名的app在加载大数量图片的性能表现(gif录制的不够

Android高效加载大图、多图解决方案,有效避免程序OOM(转)

本篇文章主要内容来自于Android Doc,我翻译之后又做了些加工,英文好的朋友也可以直接去读原文. http://developer.android.com/training/displaying-bitmaps/index.html 高效加载大图片 我们在编写Android程序的时候经常要用到许多图片,不同图片总是会有不同的形状.不同的大小,但在大多数情况下,这些图片都会大于我们程序所需要的大小.比如说系统图片库里展示的图片大都是用手机摄像头拍出来的,这些图片的分辨率会比我们手机屏幕的分辨

Android 高效加载大图,多图解决方案,有效避免程序OOM

高效加载大图片 我们在编写Android程序的时候经常要用到许多图片,不同图片总是会有不同的形状.不同的大小,但在大多数情况下,这些图片都会大于我们程序所需要的大小.比如说系统图片库里展示的图片大都是用手机摄像头拍出来的,这些图片的分辨率会比我们手机屏幕的分辨率高得多.大家应该知道,我们编写的应用程序都是有一定内存限制的,程序占用了过高的内存就容易出现OOM(OutOfMemory)异常.我们可以通过下面的代码看出每个应用程序最高可用内存是多少. [java] view plaincopy in

转载__Android--加载大分辨率图片到内存

http://www.cnblogs.com/plokmju/p/android_LoadBigImage.html#3084005 前言 在使用ImageView显示图片的时候,直接加载一个图片资源到内存中,经常会出现内存溢出的错误,这是因为有些图片的分辨率比较高,把它直接加载到内存中之后,会导致堆内存溢出的问题.这篇博客就来讲解一下Android的堆内存以及如何在Android应用中加载一个高分辨率的图片.关于ImageView不熟悉的朋友,可以看看之前的博客:Android--ImageV

有效解决Android加载大图片时内存溢出的问题

首先解析一下基本的知识: 位图模式,bitmap颜色位数是1位 灰度模式,bitmap颜色位数是8位,和256色一样 RGB模式,bitmap颜色位数是24位 在RGB模式下,一个像素对应的是红.绿.蓝三个字节 CMYK模式,bitmap颜色位数是32位  在CMYK模式下,一个像素对应的是青.品.黄.黑四个字节 图像文件的字节数(Byte) = 图像分辨率*颜色深度/8(bit/8) 例如:一幅640*480图像分辨率.RGB色一般为24位真彩色,图像未经压缩的数据容量为:640X480X24