Android Bitmap压缩策略

本文探讨了Android中为何需要高效加载Bitmap以及如何实现。由于大图可能导致内存溢出,通过设置采样率和使用BitmapFactory加载Bitmap是关键。采样率用于按比例缩小图片以减少内存占用,其值应为2的指数。通过先加载图片宽高信息,计算缩放比,再重新加载,可以避免图片拉伸模糊。高效加载流程包括设置inJustDecodeBounds为true获取宽高,计算采样率,然后重载图片。
一、为什么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 开发中,`Bitmap` 是图像处理中最常用的数据结构,但也是内存消耗大户。为了优化内存使用和提升性能,**Bitmap 压缩策略**非常重要。下面是常见的 Bitmap 压缩策略及使用方法: --- ### 一、Bitmap 压缩策略分类 #### 1. **质量压缩(Quality Compression)** **原理**:通过降低图片的 JPEG 质量来减少文件大小,不改变图片的尺寸。 **适用场景**:保存图片到本地、上传图片等。 ```java Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image); ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 100 表示不压缩,数值越小压缩率越高 bitmap.compress(Bitmap.CompressFormat.JPEG, 50, baos); byte[] compressedData = baos.toByteArray(); // 如果需要再转成 Bitmap Bitmap compressedBitmap = BitmapFactory.decodeByteArray(compressedData, 0, compressedData.length); ``` > ⚠️ 注意:JPEG 支持质量压缩,PNG 不支持(因为 PNG 是无损压缩)。 --- #### 2. **尺寸压缩(Scaling)** **原理**:按比例缩小图片的宽高,减少像素数量,从而降低内存占用。 **适用场景**:显示缩略图、头像等不需要高清图的场景。 ```java Bitmap originalBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image); float scale = 0.5f; // 缩小为原来的一半 Matrix matrix = new Matrix(); matrix.setScale(scale, scale); Bitmap scaledBitmap = Bitmap.createBitmap(originalBitmap, 0, 0, originalBitmap.getWidth(), originalBitmap.getHeight(), matrix, true); ``` --- #### 3. **采样率压缩(inSampleSize)** **原理**:加载图片时设置 `BitmapFactory.Options.inSampleSize`,按比例加载图片,减少内存占用。 **适用场景**:从资源文件或本地加载大图时。 ```java BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(getResources(), R.drawable.large_image, options); // 设置 inSampleSize 为 2,表示宽高各缩小为原来的 1/2,像素数变为 1/4 options.inJustDecodeBounds = false; options.inSampleSize = calculateInSampleSize(options, 1024, 768); Bitmap sampledBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.large_image, options); // 计算 inSampleSize 的方法 public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { final int width = options.outWidth; final int height = options.outHeight; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { final int halfWidth = width / 2; final int halfHeight = height / 2; while ((halfWidth / inSampleSize) >= reqWidth && (halfHeight / inSampleSize) >= reqHeight) { inSampleSize *= 2; } } return inSampleSize; } ``` --- #### 4. **Bitmap 内存复用(BitmapPool)** **原理**:复用已有的 Bitmap 对象,避免频繁创建和回收,减少内存抖动。 **适用场景**:频繁加载图片的场景(如 RecyclerView)。 ```java Bitmap reusableBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888); BitmapFactory.Options options = new BitmapFactory.Options(); options.inBitmap = reusableBitmap; // 复用该 Bitmap options.inJustDecodeBounds = false; Bitmap decodedBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image, options); ``` > ⚠️ 注意:`inBitmap` 要求复用的 Bitmap 必须是可变的(mutable),并且格式兼容。 --- ### 二、综合使用策略建议 | 场景 | 推荐策略 | |------|----------| | 显示缩略图 | 尺寸压缩 + inSampleSize | | 图片上传 | 质量压缩 + 尺寸压缩 | | 加载大图 | inSampleSize + BitmapFactory | | 频繁加载图片 | inBitmap + inSampleSize | --- ### ✅ 总结 | 压缩方式 | 是否改变尺寸 | 是否减少内存占用 | 是否影响画质 | 适用场景 | |----------|---------------|------------------|----------------|----------| | 质量压缩 | 否 | 否(内存)/是(文件) | 是 | 图片保存、上传 | | 尺寸压缩 | 是 | 是 | 是 | 显示缩略图 | | inSampleSize | 是 | 是 | 是 | 加载大图 | | inBitmap | 否 | 是(减少频繁分配) | 否 | 高频图片加载 | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值