You need to enable JavaScript to run this app.
导航
Glide 接入 HEIF 解码库操作说明
最近更新时间:2024.05.28 11:26:14首次发布时间:2024.05.07 15:24:06

本文为您介绍 Glide 接入 veImageX 提供的 HEIF 解码库的接入流程,实现 HEIF 加载。

注意事项

  • 当前仅支持解码 HEIF 静图,HEIF 动图暂不支持。

  • 建议使用 4.0.0 及以上版本的 Glide。

前提条件

您已完成独立 HEIF 编解码库的集成准备

添加 Maven 仓库

在 project 根目录下的build.gradle下配置服务,代码示例如下所示:

maven {
    url 'https://artifact.bytedance.com/repository/Volcengine/'
    // 最新版本号获取地址:https://artifact.bytedance.com/repository/Volcengine/
}

添加 SDK 依赖

说明

Glide 为开源图片库,建议您使用 4.0.0 及以上版本,具体版本号请见 Glide 版本历史

在 module 目录下的build.gradle文件中的dependencies中添加 SDK 依赖,代码示例如下所示。

dependencies {
    implementation("com.github.bumptech.glide:glide:xxx") // Glide 库(推荐 4.0.0 及以上版本)
    annotationProcessor("com.github.bumptech.glide:compiler:xxx") //Glide 库解码能力(推荐 4.0.0 及以上版本)
}

如果您使用 Kotlin 语言来编写 AppGlideModule,您需要使用 kapt 或者 ksp 插件实现编译处理,推荐您使用 ksp 插件。

  1. 在 gradle 项目文件中添加 ksp 插件

  2. dependencies中添加 SDK 依赖。

dependencies {
    implementation("com.github.bumptech.glide:glide:xxx") // Glide 库(推荐 4.0.0 及以上版本)
    ksp("com.github.bumptech.glide:ksp:xxx") // 使用 KSP 插件替代传统 Kotlin 注解处理器(推荐 4.0.0 及以上版本)
}
   

配置授权

在自定义的ApplicationonCreate方法中执行以下代码:

List<String> encodedAuthCode = new ArrayList<>();
encodedAuthCode.add("xxxxxxxxxxxxxxxxxxxxxxxxx");

InitConfig initConfig = new InitConfig(
        this,             // Application Context
        "000000",         // App id, 如实填写,您可在 接入准备-获取 AppID 获取
        "sample",         // App Name,暂未用到,传入app名称
        "debug",          // channel,暂未用到,传入例如OPPO  
        "0.0.1",          // App的versionName, 如实填写
        "1",              // App的versionCode, 如实填写
        "48144589260",    // device id,暂未用到
        InitConfig.CHINA, // App 上线的区域,如实填写
        "M2ZmYzkzZjUtN2", // Token,如实填写,您可在 接入准备-获取 Token 获取
        encodedAuthCode   // 授权码List<String>,如实填写,您可在 接入准备-购买授权 获取
);
CloudControl.init(initConfig);

配置解码器插件

基于 HEIF 解码库配置 Glide 解码器插件,在 decode 方法中接入 veImageX HEIF 解码库,具体参考 Glide 官方文档中的自定义组件模块,代码示例如下所示。

说明

若 HEIF 图不包含 Alpha 通道,但仍选择使用Heif.toRgb565() 解码时,将可能导致最终图片解析异常。

class HeifByteBufferBitmapDecoder(bitmapPool: BitmapPool) : ResourceDecoder<ByteBuffer, Bitmap> {

    private val bitmapPool: BitmapPool

    init {
        this.bitmapPool = Preconditions.checkNotNull(bitmapPool)
    }

    override fun handles(source: ByteBuffer, options: Options): Boolean {
        val buffer = ByteBufferUtil.toBytes(source)
        return Heif.isHeif(buffer, buffer.size)
    }

    override fun decode(
        source: ByteBuffer,
        width: Int,
        height: Int,
        options: Options
    ): Resource<Bitmap>? {
        // 将 ByteBuffer 转为 buffer 数组
        val buffer = ByteBufferUtil.toBytes(source)
        var hasAlpha = true
        // 解析图片的基本信息
        val meta = Heif.parseSimpleMeta(buffer, buffer.size)
        meta ?: return null
        if (meta.size > 8) {
            // 是否有 alpha 通道 
            hasAlpha = meta[8] != 0
        }
        // 根据是否有 alpha 通道,选择解码成不同格式
        val heifData = if (hasAlpha) {
            // 包含,使用 heif toRgba 解码
            Heif.toRgba(buffer, buffer.size, false, 1, 0, 0, meta[1], meta[0])
        } else {
            // 不包含,使用 heif toRgb565 解码
            // 注意:如果有 alpha 通道的图片强行使用 toRgb565 方式解码,可能会造成图片解析异常。
            Heif.toRgb565(buffer, buffer.size, false, 1, 0, 0, meta[1], meta[0])
        }
        heifData ?: return null
        val config: Bitmap.Config = if (hasAlpha) {
            Bitmap.Config.ARGB_8888
        } else {
            Bitmap.Config.RGB_565
        }
        val bitmap = heifData.newBitmap(config)
       // 将 HEIF 图片解码为 Bitmap
        return BitmapResource.obtain(bitmap, bitmapPool)
    }
}

注册解码器插件

使用 prepend 方法注册 HeifByteBufferBitmapDecoder 解码器,并将其指定为解码 HEIF 图像时的最高优先级解码器。以便在使用 Glide 解码 HEIF 图像时,默认会优先使用该自定义解码器。

说明

对于加载某些在线 HEIF 图像出现的异常,建议参考使用 Glide 自定义解码器插件时处理 HEIF 图时加载异常的排查建议处理。

@GlideModule
open class HeifGlideModule : AppGlideModule() {
    override fun registerComponents(
        context: Context, glide: Glide, registry: Registry
    ) {
        val byteBufferBitmapDecoder = HeifByteBufferBitmapDecoder(glide.bitmapPool)
        // 优先使用 prepend 注册的解码器
        registry.prepend(
            Registry.BUCKET_BITMAP,
            ByteBuffer::class.java,
            Bitmap::class.java,
            byteBufferBitmapDecoder
        )
    }
}

如果您是在单独的模块中封装 Glide 框架,而不是在主应用程序模块中使用 Glide,请您将 AppGlideModule 更改为 LibraryGlideModule

使用

参考 Glide 官方文档加载 HEIF 图片,具体如下所示。

Glide.with(context)
    .load("http://xxxxx.heic") // HEIF 图片的加载 URL
    .into(imageView)

常见问题

使用 Glide 自定义解码器插件时处理 HEIF 图时加载异常的排查建议。

  1. 检查依赖配置:确保HeifGlideModule类在编译构建后成功生成有效的注册代码。如果HeifGlideModule没有被其他类引用到,通常是因为 Gradle 文件配置的问题,请检查是否正确配置了 Glide 依赖,确保配置正确并成功生成目标文件。

  2. 检查注册方法:确保使用registry.prepend()接口进行解码器注册。如果您使用的是 append 方法注册,那么当 Glide 自带的解码器能够处理 HEIF 图时,将会优先使用自带解码器拦截,最终导致自定义的解码器无法得到执行。

  3. 检查缓存策略:在 Glide 中,当您需要使用自定义解码器插件处理 HEIF 时,如果设置了跳过磁盘缓存策略,Glide无法优先使用自定义解码器对图片进行解码,而会默认使用自带的解码器,这可能导致 HEIF 图像解码异常。此时,建议您采取以下操作进行排查和处理:

    1. 检查缓存策略:请确保没有设置跳过磁盘缓存的相关策略,如.diskCacheStrategy(DiskCacheStrategy.RESOURCE).diskCacheStrategy(DiskCacheStrategy.NONE)。这样 Glide 才能将图像保存到磁盘缓存,并使用自定义解码器进行解码。

    2. 清理缓存:如果之前已经设置了跳过磁盘缓存策略,或者存在旧的缓存数据,建议清理缓存。通过清理缓存,可以删除旧的缓存文件,以防止其对解码效果产生影响。您可以使用 Glide 提供的缓存清理方法或手动删除相关缓存文件。