高效加载大图片


转载出处:http://blog.csdn.net/guolin_blog/article/details/9316683

高效加载大图片

我们在编写Android程序的时候经常要用到许多图片,不同图片总是会有不同的形状、不同的大小,但在大多数情况下,这些图片都会大于我们程序所需要的大小。比如说系统图片库里展示的图片大都是用手机摄像头拍出来的,这些图片的分辨率会比我们手机屏幕的分辨率高得多。大家应该知道,我们编写的应用程序都是有一定内存限制的,程序占用了过高的内存就容易出现OOM(OutOfMemory)异常。我们可以通过下面的代码看出每个应用程序最高可用内存是多少。
[java]  view plain copy
  1. int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);  
  2. Log.d("TAG""Max memory is " + maxMemory + "KB");  
因此在展示高分辨率图片的时候,最好先将图片进行压缩。压缩后的图片大小应该和用来展示它的控件大小相近,在一个很小的ImageView上显示一张超大的图片不会带来任何视觉上的好处,但却会占用我们相当多宝贵的内存,而且在性能上还可能会带来负面影响。下面我们就来看一看,如何对一张大图片进行适当的压缩,让它能够以最佳大小显示的同时,还能防止OOM的出现。

BitmapFactory这个类提供了多个解析方法(decodeByteArray, decodeFile, decodeResource等)用于创建Bitmap对象,我们应该根据图片的来源选择合适的方法。比如SD卡中的图片可以使用decodeFile方法,网络上的图片可以使用decodeStream方法,资源文件中的图片可以使用decodeResource方法。这些方法会尝试为已经构建的bitmap分配内存,这时就会很容易导致OOM出现。为此每一种解析方法都提供了一个可选的BitmapFactory.Options参数,将这个参数的inJustDecodeBounds属性设置为true就可以让解析方法禁止为bitmap分配内存,返回值也不再是一个Bitmap对象,而是null。虽然Bitmap是null了,但是BitmapFactory.Options的outWidth、outHeight和outMimeType属性都会被赋值。这个技巧让我们可以在加载图片之前就获取到图片的长宽值和MIME类型,从而根据情况对图片进行压缩。如下代码所示:

[java]  view plain copy
  1. BitmapFactory.Options options = new BitmapFactory.Options();  
  2. options.inJustDecodeBounds = true;  
  3. BitmapFactory.decodeResource(getResources(), R.id.myimage, options);  
  4. int imageHeight = options.outHeight;  
  5. int imageWidth = options.outWidth;  
  6. String imageType = options.outMimeType;  
为了避免OOM异常,最好在解析每张图片的时候都先检查一下图片的大小,除非你非常信任图片的来源,保证这些图片都不会超出你程序的可用内存。

现在图片的大小已经知道了,我们就可以决定是把整张图片加载到内存中还是加载一个压缩版的图片到内存中。以下几个因素是我们需要考虑的:

  • 预估一下加载整张图片所需占用的内存。
  • 为了加载这一张图片你所愿意提供多少内存。
  • 用于展示这张图片的控件的实际大小。
  • 当前设备的屏幕尺寸和分辨率。

比如,你的ImageView只有128*96像素的大小,只是为了显示一张缩略图,这时候把一张1024*768像素的图片完全加载到内存中显然是不值得的。

那我们怎样才能对图片进行压缩呢?通过设置BitmapFactory.Options中inSampleSize的值就可以实现。比如我们有一张2048*1536像素的图片,将inSampleSize的值设置为4,就可以把这张图片压缩成512*384像素。原本加载这张图片需要占用13M的内存,压缩后就只需要占用0.75M了(假设图片是ARGB_8888类型,即每个像素点占用4个字节)。下面的方法可以根据传入的宽和高,计算出合适的inSampleSize值:

[java]  view plain copy
  1. public static int calculateInSampleSize(BitmapFactory.Options options,  
  2.         int reqWidth, int reqHeight) {  
  3.     // 源图片的高度和宽度  
  4.     final int height = options.outHeight;  
  5.     final int width = options.outWidth;  
  6.     int inSampleSize = 1;  
  7.     if (height > reqHeight || width > reqWidth) {  
  8.         // 计算出实际宽高和目标宽高的比率  
  9.         final int heightRatio = Math.round((float) height / (float) reqHeight);  
  10.         final int widthRatio = Math.round((float) width / (float) reqWidth);  
  11.         // 选择宽和高中最小的比率作为inSampleSize的值,这样可以保证最终图片的宽和高  
  12.         // 一定都会大于等于目标的宽和高。  
  13.         inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;  
  14.     }  
  15.     return inSampleSize;  
  16. }  
使用这个方法,首先你要将BitmapFactory.Options的inJustDecodeBounds属性设置为true,解析一次图片。然后将BitmapFactory.Options连同期望的宽度和高度一起传递到到calculateInSampleSize方法中,就可以得到合适的inSampleSize值了。之后再解析一次图片,使用新获取到的inSampleSize值,并把inJustDecodeBounds设置为false,就可以得到压缩后的图片了。
[java]  view plain copy
  1. public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,  
  2.         int reqWidth, int reqHeight) {  
  3.     // 第一次解析将inJustDecodeBounds设置为true,来获取图片大小  
  4.     final BitmapFactory.Options options = new BitmapFactory.Options();  
  5.     options.inJustDecodeBounds = true;  
  6.     BitmapFactory.decodeResource(res, resId, options);  
  7.     // 调用上面定义的方法计算inSampleSize值  
  8.     options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);  
  9.     // 使用获取到的inSampleSize值再次解析图片  
  10.     options.inJustDecodeBounds = false;  
  11.     return BitmapFactory.decodeResource(res, resId, options);  
  12. }  
下面的代码非常简单地将任意一张图片压缩成100*100的缩略图,并在ImageView上展示。
[java]  view plain copy
  1. mImageView.setImageBitmap(  
  2.     decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100100));  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: c是一种编程语言,它是由丹尼斯·里奇在1972年发明的。c语言是一种高级的、面向过程的编程语言,被广泛应用于系统编程。它拥有简洁、高效的特点,被认为是编程语言中的一种经典。 c语言的语法简洁清晰,易于理解和学习。它提供了丰富的数据类型和操作符,可以灵活地进行变量的定义和使用。它还支持数组和指针的操作,使得程序的运行效率得到提高。与其他高级语言相比,c语言的执行效率更高。此外,c语言还提供了丰富的标准库和函数,可以方便地进行各种操作和处理。 c语言广泛应用于系统编程,如操作系统、嵌入式系统等方面。由于其高效的执行速度和灵活的特性,c语言被用于开发各种应用,如编译器、数据库、网络协议等。许多著名的软件和操作系统都是用c语言编写的,如Linux操作系统、MySQL数据库等。 与其他编程语言相比,c语言的学习和使用门槛较低,但也需要掌握一定的编程基础知识。掌握c语言的基本语法和常用的函数库,可以进行基本的编程操作。但要深入了解c语言的各种特性和底层原理,需要更多的学习和实践。 总之,c语言是一种经典的编程语言,具有简洁、高效、灵活的特点。无论是初学者还是有一定编程经验的开发者,都应学习和掌握c语言,以便能够应用于各种软件和系统的开发。 ### 回答2: " c "这个字母是拉丁字母表中的第三个字母,也是英语字母表中的第三个字母。在汉语拼音中,"c"代表着声母"ch"的发音,如"车"、"吃"等。此外,在数学中,"c"可以代表复数域中的复数,与实数相对应。 在计算机科学领域,"c"是一种编程语言的名称。C语言是一种通用的高级编程语言,广泛应用于系统软件开发、嵌入式系统以及其他一些需要高效性能的领域。C语言的设计简洁且灵活,适合编写底层的系统代码。 除此之外,"C"还有其他含义。在天气预报中,"C"表示摄氏度的单位。在航空中,"C"表示航空公司的代码,用于标识航空公司。在音乐领域,"C"是音乐的一个音符,也是一个音的名称。在化学中,"C"代表着一种化学元素,即碳。 总而言之,"c"是一个广泛使用的字母,具有多个意义和用途。无论是在语言、科学、技术还是其他领域,它都扮演着重要的角色。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值