Android Bitmap.Config.HARDWARE 属性产生的来源和控制权
- HARDWARE 不是底层图片编解码器"顺手赋予"的格式;
- 它主要是由 Android Framework / Bitmap 解码流程 决定是否创建为硬件位图;
- 开发者可以在一定程度上请求/影响它是否为 HARDWARE ,但不是任何场景都能随意设置成功;
- 真正落地时,通常是 Android 系统在 Java/Framework + Native 图形栈中分配 GPU/Hardware-backed bitmap,而不是 JPEG/PNG 解码库本身决定。
1. Bitmap.Config.HARDWARE 是什么
Bitmap.Config.HARDWARE 表示这个 Bitmap 的像素数据不在普通可读写的 CPU 内存里 ,而是一个硬件加速/图形系统支持的、通常由 GPU 或图形缓冲区承载的只读位图。
它的几个关键特征:
- 通常只读
- 不能直接通过 getPixels() / copyPixelsToBuffer() 等像普通软件位图那样随意访问像素
- 不能在它上面创建可写的 Canvas
- 更适合 显示/渲染,减少上传纹理等开销
- 常用于提升图片显示性能,尤其在列表、大图展示场景
所以,HARDWARE 更像是一个位图存储后端类型,不是图片文件格式的一部分。
2. 是谁决定 Bitmap属性 config = HARDWARE ?
答案是:Android OS Framework 决定并创建出来的。
更准确地说:
- 图片文件(JPEG、PNG、WebP 等)被解码时,底层解码器首先得到的是图像像素内容;
- 但最终生成的 Bitmap 是什么 config(如 ARGB_8888、RGB_565、HARDWARE),是由 Android 的解码 API、选项参数、平台版本、当前约束条件 共同决定的;
- 如果终产物是 HARDWARE,那是 Android 平台创建了一个 hardware-backed bitmap;
- 不是 libjpeg/libpng 这种纯解码库自己说"我要生成 HARDWARE bitmap"。
可以这样理解:
- 底层解码库负责"把图片解出来"
- Android 图形/Bitmap 系统负责"把解码结果放进什么类型的 Bitmap 容器里"
所以主导方是 Android OS / Framework / Native graphics pipeline,不是图片编解码平台单独决定。
3. 开发者能自己设置Bitmap属性 HARDWARE 吗?
可以"请求",但底层系统不保证成功。
对于解码器 ImageDecoder
ImageDecoder 是 Android 9(API 28)后现代的解码方式,它支持 allocator 选项。
开发者可以通过类似方式指定:
ImageDecoder.decodeBitmap(source, (decoder, info, source1) -> {
decoder.setAllocator(ImageDecoder.ALLOCATOR_HARDWARE);
});
这表示:
- 开发者明确要求尽量解码成硬件位图
- 如果平台和场景允许,最终得到的 Bitmap.getConfig() 就可能是 Bitmap.Config.HARDWARE
但注意:
- 如果当前条件不允许,系统可能失败,退回其他形式(具体行为取决于 API 和场景)
- 并不是 100% 一定成功
对 BitmapFactory
BitmapFactory 没有像 ImageDecoder.setAllocator() 那样直接、现代化的公开"硬件分配器"接口。
但从 Android O(API 26)开始,BitmapFactory.Options 引入了一个重要选项:
options.inPreferredConfig = Bitmap.Config.HARDWARE;
这表示开发者可以偏好解码为 HARDWARE。
但同样需要注意:
- 这是一个请求/偏好
- 是否真的返回 HARDWARE,由平台判断
- 某些情况下系统不会按这个偏好执行
4. 如果开发者不设置,系统会不会自己给成 HARDWARE?
会,在某些 API/框架/库的默认策略下有可能。
比如:
- 某些图片加载库(如 Glide、Coil新版本/特定配置)在 Android 8.0+ 可能会优先使用 hardware bitmap 来优化显示性能;
- 某些系统应用(例如图库、相册、媒体浏览器)为了显示性能,可能在内部 decode 选项上主动启用硬件位图;
- ImageDecoder 在某些默认策略和目标用途下,也可能倾向于产生更适合渲染的位图。
也就是说:
- 如果图库应用解出来的Bitmap是 HARDWARE
- 更大概率是 图库应用的解码逻辑/Android framework 的默认或显式策略 导致
- 而不是"底层解码芯片自动把它变成 HARDWARE"
5. HARDWARE 是在 OS 层赋值,还是底层平台赋值?
更准确的说法是:
主要是 Android OS/framework 侧决定并标记
Bitmap 的 config 是 Android Bitmap 对象的一个属性,它反映的是这个 bitmap 底层像素存储方式。
当平台创建一个 hardware-backed bitmap 时,应用层看到的 config 就是 Bitmap.Config.HARDWARE。
所以从职责划分看:
1)图片解码器/codec
负责把压缩图片数据还原成像素
2)Android Native/Graphics/Bitmap 层
负责分配 bitmap 承载对象:
- 普通堆内存软件位图
- 或 hardware-backed 位图
3)Java Framework API
把这个结果暴露成 Bitmap,其 config 显示为 HARDWARE
所以它不是一个"底层硬件解码平台回填给 Java 的任意属性",而是Android 平台创建位图时确定下来的类型信息。
6. 开发者能不能把一个已有 Bitmap 的 config 改成 HARDWARE?
一般不能直接"改属性"。
Bitmap 的 config 不是一个可随便 setter 改写的字段。
开发者不能这样做:
bitmap.setConfig(Bitmap.Config.HARDWARE); // 不存在这种能力
如果想得到一个 HARDWARE bitmap,通常是:
- 在解码时指定/请求
- 或者通过某些复制/转换路径让系统重新创建一个新的 bitmap
但这里也有个重要点:
HARDWARE bitmap 不是普通意义上想 copy 就 copy 的软件位图
很多转换会受到限制,因为GPU硬件位图是只读且不能直接 CPU 访问。
7. 为什么系统要搞 HARDWARE 这种 config?
核心原因是显示性能优化。
普通software Bitmap在 CPU 可访问内存里。显示到屏幕时,需要:
- 上传到 GPU 纹理
- 做额外内存复制
- 增加 UI 渲染负担
而 HARDWARE bitmap:
- 更适合直接参与 GPU 渲染
- 减少重复上传和中间开销
- 对滚动列表、图片浏览等场景更友好
这也是为什么图库类应用比较容易看到它。
8. 为什么不是所有图片都默认用 HARDWARE?
因为它也有明显限制:
限制包括:
- 不可变
- 不能直接读写像素
- 一些图像处理操作不支持
- 某些 Canvas 绘制路径或兼容场景有限制
- 过度使用会带来图形内存压力
- 在某些跨进程、截图、共享或软件处理流程中不合适
因此系统不会无脑全部设成 HARDWARE,而是根据用途选择。
9. 实际上"是谁说了算"?
一句工程上最准确的话总结:
Bitmap.Config.HARDWARE 是 Android 平台在解码/创建 Bitmap 过程中,根据开发者选项、框架默认策略、运行环境和硬件能力约束条件下共同参与决定生成的一种 hardware-backed Bitmap 配置;它不是图片编解码格式自身携带的信息,也不是开发者对已有 Bitmap 可任意改写的普通属性。
10. 结论
1)HARDWARE 是怎么配置/赋值或产生的?
是在 Android 解码与 Bitmap 创建流程中 产生的。
当系统决定创建 hardware-backed bitmap 时,这个 Bitmap 的 config 就表现为 HARDWARE。
2)是 Android OS 系统还是底层解码平台赋予的?
主要是 Android OS / Framework / Native graphics stack 赋予的。
底层解码器负责解码像素,不是它独立定义 Java Bitmap.Config。
3)开发者可以灵活设置该属性吗?
可以在解码阶段请求或偏好使用 HARDWARE,例如:
- ImageDecoder.setAllocator(ImageDecoder.ALLOCATOR_HARDWARE)
- BitmapFactory.Options.inPreferredConfig = Bitmap.Config.HARDWARE
但:
- 这不是对任何已有 Bitmap 的任意改属性
- 不是 100% 保证成功
- 受平台版本、场景和限制条件影响
11. 一个简单判断标准
实用的判断:
- 文件格式决定不了 HARDWARE
- 解码库本身不单独决定 HARDWARE
- Android 平台在创建 Bitmap 时决定是否为 HARDWARE
- 开发者只能"申请/引导",不能对结果绝对强制,也不能随意改已有对象
从 AOSP 源码路径看,BitmapFactory 走到 Bitmap.Config.HARDWARE 的关键不是"底层解码器直接输出了硬件位图",而是:
BitmapFactory在 JNI 层解析到目标 config 为 HARDWARE 后,转入 Android native graphics / hwui 的硬件位图创建流程,由 GraphicBuffer / AHardwareBuffer 等图形资源承载解码结果,最终返回一个 hardware-backed Java Bitmap。