`

Android Bitmap压缩策略

阅读更多

一、为什么Bitmap需要高效加载?

现在的高清大图,动辄就要好几M,而Android对单个应用所施加的内存限制,只有
小几十M,如16M,这导致加载Bitmap的时候很容易出现内存溢出。如下异常信
息,便是在开发中经常需要的:

java.lang.OutofMemoryError:bitmap size exceeds VM budget

为了解决这个问题,就出现了Bitmap的高效加载策略。其实核心思想很简单。假设
通过ImageView来显示图片,很多时候ImageView并没有原始图片的尺寸那么大,
这个时候把整个图片加载进来后再设置给ImageView,显然是没有必要的,因为
ImageView根本没办法显示原始图片。这时候就可以按一定的采样率来将图片缩小
后再加载进来,这样图片既能在ImageView显示出来,又能降低内存占用从而在一
定程度上避免OOM,提高了Bitmap加载时的性能

二、Bitmap高效加载的具体方式

1.加载Bitmap的方式

Bitmap在Android中指的是一张图片。通过BitmapFactory类提供的四类方法:
decodeFile,decodeResource,decodeStreamdecodeByteArray,分别从文件系统,
资源,输入流和字节数组中加载出一个Bitmap对象,其中
decodeFile,decodeResource又间接调用了decodeStream方法,这四类方法最终是
在Android的底层实现的,对应着BitmapFactory类的几个native方法。

2.BitmapFactory.Options的参数

inSampleSize参数
上述四类方法都支持BitmapFactory.Options参数,而Bitmap的按一定采样率进行缩
放就是通过BitmapFactory.Options参数实现的,主要用到了inSampleSize参数,即
采样率。通过对inSampleSize的设置,对图片的像素的高和宽进行缩放。

inSampleSize=1,即采样后的图片大小为图片的原始大小。小于1,也按照1来计
算。 当inSampleSize>1,即采样后的图片将会缩小,缩放比例为1/(inSampleSize
的二次方)。

例如: 一张1024 ×1024像素的图片,采用ARGB8888格式存储,那么内存大小
1024×1024×4=4M。如果inSampleSize=2,那么采样后的图片内存大小:
512×512×4=1M。

注意: 官方文档支出,inSampleSize的取值应该总是2的指数,如1,2,4,8等。
如果外界传入的inSampleSize的值不为2的指数,那么系统会向下取整并选择一个
最接近2的指数来代替。比如3,系统会选择2来代替。当时经验证明并非在所有
Android版本上都成立。

关于inSampleSize取值的注意事项: 通常是根据图片宽高实际的大小/需要的宽高
大小,分别计算出宽和高的缩放比。但应该取其中最小的缩放比,避免缩放图片太
小,到达指定控件中不能铺满,需要拉伸从而导致模糊。

例如: ImageView的大小是100×100像素,而图片的原始大小为200×300,那么宽
的缩放比是2,高的缩放比是3。如果最终inSampleSize=2,那么缩放后的图片大小
100×150,仍然合适ImageView。如果inSampleSize=3,那么缩放后的图片大小小
ImageView所期望的大小,这样图片就会被拉伸而导致模糊。

inJustDecodeBounds参数
我们需要获取加载的图片的宽高信息,然后交给inSampleSize参数选择缩放比缩
放。那么如何能先不加载图片却能获得图片的宽高信息,通过
inJustDecodeBounds=true,然后加载图片就可以实现只解析图片的宽高信息,并
不会真正的加载图片,所以这个操作是轻量级的。当获取了宽高信息,计算出缩放
比后,然后在将inJustDecodeBounds=false,再重新加载图片,就可以加载缩放后
的图片。

注意: BitmapFactory获取的图片宽高信息和图片的位置以及程序运行的设备有
关,比如同一张图片放在不同的drawable目录下或者程序运行在不同屏幕密度的设
备上,都可能导致BitmapFactory获取到不同的结果,和Android的资源加载机制
有关

3.高效加载Bitmap的流程

①将BitmapFactory.OptionsinJustDecodeBounds参数设为true并加载图片。
②从BitmapFactory.Options中取出图片的原始宽高信息,它们对应于outWidth
outHeight参数。

③根据采样率的规则并结合目标View的所需大小计算出采样率inSampleSize
④将BitmapFactory.OptionsinJustDecodeBounds参数设为false,然后重新加载
图片。

三、Bitmap高效加载的代码实现

  public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight){
     BitmapFactory.Options options = new BitmapFactory.Options();
     options.inJustDecodeBounds = true;
     //加载图片
     BitmapFactory.decodeResource(res,resId,options);
     //计算缩放比
     options.inSampleSize = calculateInSampleSize(options,reqHeight,reqWidth);
     //重新加载图片
     options.inJustDecodeBounds =false;
     return BitmapFactory.decodeResource(res,resId,options);
  }

  private static int calculateInSampleSize(BitmapFactory.Options options, int reqHeight, int reqWidth) {
     int height = options.outHeight;
     int width = options.outWidth;
     int inSampleSize = 1;
     if(height>reqHeight||width>reqWidth){
         int halfHeight = height/2;
         int halfWidth = width/2;
         //计算缩放比,是2的指数
         while((halfHeight/inSampleSize)>=reqHeight&&(halfWidth/inSampleSize)>=reqWidth){
               inSampleSize*=2;
         }
     }

     return inSampleSize;
  }

这个时候就可以通过如下方式高效加载图片:

  mImageView.setImageBitmap(decodeSampledBitmapFromResource(getResources(),R.mipmap.ic_launcher,100,100);

除了BitmapFactorydecodeResource方法,其他方法也可以类似实现。

更多内容详情请关注我的GitHub:https://github.com/xiangjiana/Android-MS

分享到:
评论

相关推荐

    Android Bitmap压缩方法的选择详解

    本篇文章将深入探讨Android Bitmap的压缩方法,特别是如何选择合适的压缩策略以适应不同的场景需求,特别是在处理分享到社交平台如微信时的32KB大小限制。 首先,我们来看一下问题的背景:在测试过程中,发现将文章...

    Android中把bitmap存成BMP格式图片的方法

    在Android开发中,有时我们需要将Bitmap对象转换成不同的图片格式,比如BMP。BMP(Bitmap File Format)是一种常见的位图文件格式,但它并不像JPEG或PNG那样被Android SDK直接支持。本文将详细介绍如何在Android中将...

    Android Bitmap压缩方式分析

    本文将深入探讨Android Bitmap的压缩策略。 首先,Bitmap的压缩分为两种类型:质量压缩和尺寸压缩。质量压缩主要针对图片的质量,不改变图片的实际尺寸,而是降低颜色深度或使用有损压缩算法,以减小文件大小。尺寸...

    Android实现图片压缩(bitmap的六种压缩方式)

    在实际应用中,开发者可以根据需求和场景选择合适的压缩策略。例如,如果需要在网络上传输图片,质量压缩更适合;如果希望在本地存储大量图片,采样率压缩可能更为合适。同时,要注意压缩与图片质量的平衡,过度压缩...

    android bitmap compress(图片压缩)代码

    在Android开发中,图片压缩是一个常见的需求,特别是在处理用户拍摄的照片或从资源中加载大图时。Bitmap类是Android系统用于处理图像的主要工具,而BitmapFactory则是用来解码图片数据的关键类。本文将深入探讨如何...

    Android Bitmap 相关

    在Android平台上,Bitmap是用于表示图像数据的核心类。Bitmap对象持有像素数据,这些数据可以用于在屏幕上显示图像或进行各种图像处理操作。由于Bitmap对象占用大量内存,因此在Android开发中,正确管理和使用Bitmap...

    Android传递Bitmap对象在两个Activity之间

    在Android开发中,有时我们需要在不同的Activity之间传递数据,其中包括Bitmap对象。Bitmap是Android系统用于表示图像的一种...同时,合理地压缩和优化Bitmap尺寸,降低内存占用,也是处理Bitmap时需要考虑的重要因素。

    Android中图片压缩方案详解样本.doc

    总结来说,Android中的图片压缩主要有质量和采样率两种策略。质量压缩法主要针对文件大小的需求,而采样率压缩法则更注重减少内存消耗。开发者需要根据实际应用场景来选择合适的压缩方法。在处理大量图片或者低内存...

    关于Android bitmap你不知道的一些事

    关于Android Bitmap,这是一个重要的主题,因为它涉及到Android应用的性能和用户体验。Bitmap对象是Android系统用于存储和处理图像的核心类,但如果不正确...合理的Bitmap处理策略能够显著提升应用的稳定性和用户体验。

    android中的Bitmap相关[归类].pdf

    Bitmap是Android平台中用于处理图像的核心类,它用于表示位图图像数据。由于Bitmap对象消耗大量的内存,因此在处理时需要特别注意性能优化。...因此,开发者需要深入理解Bitmap的工作原理,掌握有效的优化策略。

    Android中图片压缩方案详细讲解.doc

    在实际应用中,开发者可以根据具体需求选择合适的压缩策略,或者结合两者以达到最佳效果。同时,还可以考虑使用第三方库,如 Glide 或 Picasso,它们提供了更高级的图片加载和压缩功能,可以简化开发流程并优化性能...

    Android截取视频帧并转化为Bitmap示例

    8. 使用`FileOutputStream`将Bitmap压缩为JPEG格式并写入文件,压缩质量设置为80。 需要注意的是,`getFrameAtTime()`方法有第二个可选参数,用于指定时间匹配策略。在这个示例中,我们使用了`...

    Android 开发绕不过的坑:你的 Bitmap 究竟占多大内存?1

    在开发中,为避免 Bitmap 引起的内存问题,我们可以采取以下策略: 1. 使用合适的资源目录(如 ldpi、mdpi、hdpi、xhdpi 等)提供相应分辨率的图片,系统会自动选择最适合的资源。 2. 对于大图,考虑使用缩略图或在...

    Android开发之图片压缩工具类完整实例

    在Android开发中,图片压缩是一项常见的任务,尤其在处理用户上传、下载或显示大图时,...在实际开发中,还需要考虑到不同设备的屏幕尺寸和内存限制,灵活调整压缩策略,确保用户体验的同时,保证应用的稳定性和效率。

    Android中3种图片压缩处理方法

    在Android开发中,图片压缩是优化应用性能和节省资源的关键技术。本文将详细介绍三种常见的Android图片压缩处理方法:质量压缩、获取...开发者需要根据具体应用场景选择合适的压缩策略,以达到最佳的用户体验和性能。

    android 将图片压缩到指定的大小的示例

    接着是核心的`compressBitmap`方法,它结合了分辨率压缩和质量压缩两种策略。首先,调用`compressByResolution`对图片进行初步的分辨率压缩。然后,创建一个`ByteArrayOutputStream`对象`baos`用于存储压缩后的图片...

    Android图片压缩以及优化实例

    除了基本的压缩方法,还有其他优化策略,如使用LruCache或 Fresco、 Glide等图片加载库进行缓存管理和内存管理,避免因大量图片加载导致的内存问题。另外,根据应用场景选择合适的图片格式(如WebP),也能显著减少...

    android图片压缩的3种方法实例

    在Android开发中,图片压缩是一项常见的任务,尤其在处理用户上传、存储或显示大量图片时。以下是Android图片压缩的三种方法实例的详细说明:...在处理大量图片时,合理的压缩策略对于优化应用性能和用户体验至关重要。

    Android图片缓存之Bitmap详解(一)

    - `compress(CompressFormat format, int quality, OutputStream stream)` 将Bitmap压缩为指定格式(如PNG或JPEG),并按给定的质量级别写入输出流。 5. **Bitmap创建**: - `createBitmap(Bitmap src)` 创建一个...

    Android拍照得到全尺寸图片并进行压缩

    在Android开发中,获取全尺寸图片并进行压缩是一项常见的需求,尤其在处理用户拍照或从图库选择照片时。...同时,压缩策略也可以根据应用的具体需求进行调整,比如使用更复杂的算法来平衡图像质量和文件大小。

Global site tag (gtag.js) - Google Analytics