当前位置: 首页 > news >正文

Android 基础技术——Bitmap

笔者希望做一个系列,整理 Android 基础技术,本章是关于 Bitmap 

Bitmap 内存如何计算

占用内存 = 宽 * 缩放比例 * 高 * 缩放比例 * 每个像素所占字节

缩放比例 = 设备dpi/图片所在目录的dpi

Bitmap加载优化?不改变图片质量的情况下怎么优化?

不同的Conifg代表每个像素不同的占用空间,所以如果我们把默认的ARGB_8888改成RGB_565,那么每个像素占用空间就会由4字节变成2字节了,那么图片所占内存就会减半了。

inSampleSize,采样率,这个参数是用于图片尺寸压缩的,他会在宽高的维度上每隔inSampleSize个像素进行一次采集,从而达到缩放图片的效果。这种方法只会改变图片大小,不会影响图片质量。

inJustDecodeBounds是什么?

要获取图片本身的大小,如果直接decodeResource加载一遍的话,那么就会增加内存了,所以官方提供了这样一个参数inJustDecodeBounds。如果inJustDecodeBounds为ture,那么decode的bitmap为null,也就是不返回实际的bitmap,只把图片的大小信息放到了options的值中。

所以这个参数就是用来获取图片的大小信息的同时不占用内存

Bitmap内存复用怎么实现
  • inBitmap要和inMutable属性配套使用,否则将无法复用。
  • 在Android 4.4之前,只能重用相同大小的 Bitmap 内存区域;4.4之后只要复用内存空间的Bitmap对象大小比  inBitmap指向的内存空间要小即可。

所以一般在复用之前,还要判断下,新的Bitmap内存是不是小于可以复用的Bitmap内存,然后才能进行复用。

高清大图加载该怎么处理?

要对图片进行局部显示,这就用到BitmapRegionDecoder属性,主要用于显示图片的某一块矩形区域。

fun setImagePart() {
        val inputStream: InputStream = assets.open("test.jpg")
        val bitmapRegionDecoder: BitmapRegionDecoder =
            BitmapRegionDecoder.newInstance(inputStream, false)
        val options = BitmapFactory.Options()
        val bitmap = bitmapRegionDecoder.decodeRegion(
            Rect(0, 0, 100, 100), options)
        image.setImageBitmap(bitmap)
    }

如何跨进程传递大图?
  • Bundle直接传递。bundle最常用于Activity间传递,也属于跨进程的一种方式,但是传递的大小有限制,一般为1M

Bitmap之所以可以直接传递,是因为其实现了Parcelable接口进行了序列化。而Parcelable的传递原理是利用了Binder机制,将Parcel序列化的数据写入到一个共享内存(缓冲区)中,读取的时候也会从这个缓冲区中去读取字节流,然后再反序列化成对象使用。这个共享内存也就是缓存区有一个大小限制—1M,而且是公用的。所以传图片的话很容易就容易超过这个大小然后报错TransactionTooLargeException。

所以这个方案不可靠。

文件传输

将图片保存到文件,然后只传输文件路径,这样肯定是可以的,但是不高效

putBinder

//传递binder
val bundle = Bundle()
bundle.putBinder("bitmap", BitmapBinder(mBitmap))//接收binder中的bitmap
val imageBinder: BitmapBinder = bundle.getBinder("bitmap") as BitmapBinder
val bitmap: Bitmap? = imageBinder.getBitmap()//Binder子类
class BitmapBinder :Binder(){private var bitmap: Bitmap? = nullfun ImageBinder(bitmap: Bitmap?) {this.bitmap = bitmap}fun getBitmap(): Bitmap? {return bitmap}
}

为什么用putBinder就没有大小限制了呢?

  • 因为putBinder中传递的其实是一个文件描述符fd,文件本身被放到一个共享内存中,然后获取到这个fd之后,只需要从共享内存中取出Bitmap数据即可,这样传输就很高效了。

(文件路径不也是?其实不同,文件描述符还用到 Mmap 虚拟内存和实际物理内存映射,更加高效)

  • 而用Intent/bundle直接传输的时候,会禁用文件描述符fd,只能在parcel的缓存区中分配空间来保存数据,所以无法突破1M的大小限制。

文件描述符是一个简单的整数,用以标明每一个被进程所打开的文件和socket。第一个打开的文件是0,第二个是1,依此类推。

http://www.lryc.cn/news/290320.html

相关文章:

  • 数据结构奇妙旅程之七大排序
  • 【JavaScript】Generator
  • 河南省考后天网上确认,请提前准备证件照哦
  • 【前端】防抖和节流
  • 【网络】:网络套接字(UDP)
  • Linux编程 1/2 数据结构
  • 【UE Niagara】实现闪电粒子效果的两种方式
  • js数组/对象的深拷贝与浅拷贝
  • HCIA学习第六天:OSPF:开放式最短路径优先协议
  • 从四个方面来解决企业在项目管理中遇到的各类问题
  • 使用代码取大量2*2像素图片各通道均值,存于Excel文件中。
  • React16源码: React中commit阶段的commitBeforeMutationLifecycles的源码实现
  • 压制二元组的总价值
  • 【习题】保存应用数据
  • Flask框架小程序后端分离开发学习笔记《5》简易服务器代码
  • “计算机视觉处理设计开发工程师”专项培训(第二期)
  • R语言学习case7:ggplot基础画图(核密度图)
  • Ubuntu18配置Docker
  • Keil/MDK平台 - 结构体成员指针注意事项
  • 一款超级好用的远程控制APP,你值得拥有
  • NumPy必知必会50例 | 18. 使用 NumPy 解决线性方程组:数学问题的实用解决方案
  • C/C++编码问题研究
  • 二刷代码随想录|Java版|回溯算法3|子集问题
  • mongodb config
  • pytorch 实现中文文本分类
  • 【MySQL】聚合函数和内置函数
  • python第五节:集合set(4)
  • 知识笔记(一百)———什么是okhttp?
  • Electron桌面应用实战:Element UI 导航栏橙色轮廓之谜与Bootstrap样式冲突解决方案
  • Nuget包缓存存放位置迁移