美文网首页
性能优化<第十一篇>:webp技术

性能优化<第十一篇>:webp技术

作者: NoBugException | 来源:发表于2021-07-07 21:07 被阅读0次

    从Android 4.0开始,Android开始支持webp格式图片的编码和解码,但Android4.0~4.3之间仍然有些手机不支持webp,正确的说,从Android4.3开始支持webp。
    为了解决webp兼容性问题,我们通过ndk的方式来解决。

    [第一步]

    在网络上下载libwebp源码,地址是:
    https://www.linuxfromscratch.org/blfs/view/systemd/general/libwebp.html
    
    下载最新版本的源码。
    

    [第二步] 添加ENABLE_SHARED

    打开Android.mk,并添加:
    
        ENABLE_SHARED := 1
    

    如图:

    image.png

    [第三步] 添加libwebp_java_wrap

    打开Android.mk,并添加:
    
        swig/libwebp_java_wrap.c \
    

    如图:

    image.png

    [第四步] 创建Application.mk

    在libwebp工程中新建文件Application.mk,并添加代码:
    
        APP_ABI := armeabi-v7a
        APP_PLATFORM := android-14
    
    image.png

    [第五步] 重命名

    将libwebp工程重命名成jni
    

    [第六步] 打包so文件

    切换到jni文件夹,执行D:\android_sdk\ndk-bundle\ndk-build.cmd,执行过程如下:
    
    
    E:\Project\libwebp-1.2.0.tar\jni>D:\android_sdk\ndk-bundle\ndk-build.cmd
    Android NDK: android-14 is unsupported. Using minimum supported version android-16.
    [armeabi-v7a] Compile thumb  : cwebp <= cwebp.c
    [armeabi-v7a] Compile arm    : webpdemux <= anim_decode.c
    [armeabi-v7a] Compile arm    : webpdemux <= demux.c
    [armeabi-v7a] Compile arm    : webp <= cost.c
    [armeabi-v7a] Compile arm    : webp <= cost_mips32.c
    [armeabi-v7a] Compile arm    : webp <= cost_mips_dsp_r2.c
    [armeabi-v7a] Compile arm    : webp <= cost_neon.c
    [armeabi-v7a] Compile arm    : webp <= cost_sse2.c
    [armeabi-v7a] Compile arm    : webp <= enc.c
    [armeabi-v7a] Compile arm    : webp <= enc_mips32.c
    [armeabi-v7a] Compile arm    : webp <= enc_mips_dsp_r2.c
    [armeabi-v7a] Compile arm    : webp <= enc_msa.c
    [armeabi-v7a] Compile arm    : webp <= enc_neon.c
    [armeabi-v7a] Compile arm    : webp <= enc_sse2.c
    [armeabi-v7a] Compile arm    : webp <= enc_sse41.c
    [armeabi-v7a] Compile arm    : webp <= lossless_enc.c
    [armeabi-v7a] Compile arm    : webp <= lossless_enc_mips32.c
    [armeabi-v7a] Compile arm    : webp <= lossless_enc_mips_dsp_r2.c
    [armeabi-v7a] Compile arm    : webp <= lossless_enc_msa.c
    [armeabi-v7a] Compile arm    : webp <= lossless_enc_neon.c
    [armeabi-v7a] Compile arm    : webp <= lossless_enc_sse2.c
    [armeabi-v7a] Compile arm    : webp <= lossless_enc_sse41.c
    [armeabi-v7a] Compile arm    : webp <= ssim.c
    [armeabi-v7a] Compile arm    : webp <= ssim_sse2.c
    [armeabi-v7a] Compile arm    : webp <= alpha_enc.c
    [armeabi-v7a] Compile arm    : webp <= analysis_enc.c
    [armeabi-v7a] Compile arm    : webp <= backward_references_cost_enc.c
    [armeabi-v7a] Compile arm    : webp <= backward_references_enc.c
    [armeabi-v7a] Compile arm    : webp <= config_enc.c
    [armeabi-v7a] Compile arm    : webp <= cost_enc.c
    [armeabi-v7a] Compile arm    : webp <= filter_enc.c
    [armeabi-v7a] Compile arm    : webp <= frame_enc.c
    [armeabi-v7a] Compile arm    : webp <= histogram_enc.c
    [armeabi-v7a] Compile arm    : webp <= iterator_enc.c
    [armeabi-v7a] Compile arm    : webp <= near_lossless_enc.c
    [armeabi-v7a] Compile arm    : webp <= picture_enc.c
    [armeabi-v7a] Compile arm    : webp <= picture_csp_enc.c
    [armeabi-v7a] Compile arm    : webp <= picture_psnr_enc.c
    [armeabi-v7a] Compile arm    : webp <= picture_rescale_enc.c
    [armeabi-v7a] Compile arm    : webp <= picture_tools_enc.c
    [armeabi-v7a] Compile arm    : webp <= predictor_enc.c
    [armeabi-v7a] Compile arm    : webp <= quant_enc.c
    [armeabi-v7a] Compile arm    : webp <= syntax_enc.c
    [armeabi-v7a] Compile arm    : webp <= token_enc.c
    [armeabi-v7a] Compile arm    : webp <= tree_enc.c
    [armeabi-v7a] Compile arm    : webp <= vp8l_enc.c
    [armeabi-v7a] Compile arm    : webp <= webp_enc.c
    [armeabi-v7a] Compile arm    : webp <= bit_writer_utils.c
    [armeabi-v7a] Compile arm    : webp <= huffman_encode_utils.c
    [armeabi-v7a] Compile arm    : webp <= quant_levels_utils.c
    [armeabi-v7a] Compile arm    : webp <= libwebp_java_wrap.c
    [armeabi-v7a] Compile thumb  : cpufeatures <= cpu-features.c
    [armeabi-v7a] StaticLibrary  : libcpufeatures.a
    [armeabi-v7a] Compile arm    : webpdecoder_static <= alpha_dec.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= buffer_dec.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= frame_dec.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= idec_dec.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= io_dec.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= quant_dec.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= tree_dec.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= vp8_dec.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= vp8l_dec.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= webp_dec.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= alpha_processing.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= alpha_processing_mips_dsp_r2.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= alpha_processing_neon.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= alpha_processing_sse2.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= alpha_processing_sse41.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= cpu.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= dec.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= dec_clip_tables.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= dec_mips32.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= dec_mips_dsp_r2.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= dec_msa.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= dec_neon.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= dec_sse2.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= dec_sse41.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= filters.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= filters_mips_dsp_r2.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= filters_msa.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= filters_neon.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= filters_sse2.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= lossless.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= lossless_mips_dsp_r2.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= lossless_msa.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= lossless_neon.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= lossless_sse2.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= rescaler.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= rescaler_mips32.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= rescaler_mips_dsp_r2.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= rescaler_msa.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= rescaler_neon.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= rescaler_sse2.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= upsampling.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= upsampling_mips_dsp_r2.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= upsampling_msa.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= upsampling_neon.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= upsampling_sse2.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= upsampling_sse41.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= yuv.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= yuv_mips32.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= yuv_mips_dsp_r2.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= yuv_neon.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= yuv_sse2.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= yuv_sse41.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= bit_reader_utils.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= color_cache_utils.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= filters_utils.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= huffman_utils.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= quant_levels_dec_utils.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= random_utils.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= rescaler_utils.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= thread_utils.c
    [armeabi-v7a] Compile arm    : webpdecoder_static <= utils.c
    [armeabi-v7a] StaticLibrary  : libwebpdecoder_static.a
    [armeabi-v7a] SharedLibrary  : libwebp.so
    [armeabi-v7a] SharedLibrary  : libwebpdemux.so
    [armeabi-v7a] Compile thumb  : example_util <= example_util.c
    [armeabi-v7a] StaticLibrary  : libexample_util.a
    [armeabi-v7a] Compile thumb  : imagedec <= image_dec.c
    [armeabi-v7a] Compile thumb  : imagedec <= jpegdec.c
    [armeabi-v7a] Compile thumb  : imagedec <= metadata.c
    [armeabi-v7a] Compile thumb  : imagedec <= pngdec.c
    [armeabi-v7a] Compile thumb  : imagedec <= pnmdec.c
    [armeabi-v7a] Compile thumb  : imagedec <= tiffdec.c
    [armeabi-v7a] Compile thumb  : imagedec <= webpdec.c
    [armeabi-v7a] StaticLibrary  : libimagedec.a
    [armeabi-v7a] Compile thumb  : imageio_util <= imageio_util.c
    [armeabi-v7a] StaticLibrary  : libimageio_util.a
    [armeabi-v7a] Executable     : cwebp
    [armeabi-v7a] Install        : cwebp => libs/armeabi-v7a/cwebp
    [armeabi-v7a] Compile thumb  : dwebp <= dwebp.c
    [armeabi-v7a] Compile thumb  : imageenc <= image_enc.c
    [armeabi-v7a] StaticLibrary  : libimageenc.a
    [armeabi-v7a] Executable     : dwebp
    [armeabi-v7a] Install        : dwebp => libs/armeabi-v7a/dwebp
    [armeabi-v7a] Compile thumb  : img2webp_example <= img2webp.c
    [armeabi-v7a] Compile arm    : webpmux <= anim_encode.c
    [armeabi-v7a] Compile arm    : webpmux <= muxedit.c
    [armeabi-v7a] Compile arm    : webpmux <= muxinternal.c
    [armeabi-v7a] Compile arm    : webpmux <= muxread.c
    [armeabi-v7a] SharedLibrary  : libwebpmux.so
    [armeabi-v7a] Executable     : img2webp_example
    [armeabi-v7a] Install        : img2webp_example => libs/armeabi-v7a/img2webp_example
    [armeabi-v7a] Install        : libwebp.so => libs/armeabi-v7a/libwebp.so
    [armeabi-v7a] SharedLibrary  : libwebpdecoder.so
    [armeabi-v7a] Install        : libwebpdecoder.so => libs/armeabi-v7a/libwebpdecoder.so
    [armeabi-v7a] Install        : libwebpdemux.so => libs/armeabi-v7a/libwebpdemux.so
    [armeabi-v7a] Compile thumb  : webpinfo_example <= webpinfo.c
    [armeabi-v7a] Executable     : webpinfo_example
    [armeabi-v7a] Install        : webpinfo_example => libs/armeabi-v7a/webpinfo_example
    [armeabi-v7a] Install        : libwebpmux.so => libs/armeabi-v7a/libwebpmux.so
    [armeabi-v7a] Compile thumb  : webpmux_example <= webpmux.c
    [armeabi-v7a] Executable     : webpmux_example
    [armeabi-v7a] Install        : webpmux_example => libs/armeabi-v7a/webpmux_example
    
    最后在jni同级路径下找到libs文件夹,如图:
    
    image.png
    以及libwebp.so文件
    
    image.png

    [第七步] 集成so文件和jar文件

    一般情况下,使用
        BitmapFactory.decodeXXX
    解码一张图片,包括webp格式的图片,但是Android 4.0~4.3可能不支持webp,低于Android 4.0肯定不支持webp,
    为了保证兼容,需要集成libwebp.so文件。
    
    1、将libwebp.jar文件放入项目的libs文件夹中
    
    libwebp.jar文件可以在\jni\swig中可以找到,放到app/libs中。
    
    image.png
    2、将libwebp.so文件放入项目的main/jniLibs/文件夹中
    
    image.png
    一般情况下,只需要armeabi-v7a架构的so文件即可。但是,如果想在Android 模拟器中运行,
    Android模拟器的CPU架构大部分是x86或者x86_64,所以需要集成对应的so文件。
    
    3、当然,so库和jar的引入代码别忘记
    
    android {
    
        ...
    
        sourceSets {
            main {
                jniLibs.srcDirs = ['src/main/jniLibs']
            }
        }
    }
    
    dependencies {
        ...
        implementation files('libs/libwebp.jar')
    }
    
    4、在Application或者Activity初始化的时候加载so文件
    
        System.loadLibrary("webp");
    
    5、另外,补充一点
    
    在libwebp工程的Application.mk文件中,如果将:
    
        APP_ABI := armeabi-v7a
    
    改成
    
        APP_ABI := all
    
    那么,打包so文件时,会生成arm64-v8a、armeabi-v7a、x86、x86_64这四种CPU架构的so文件。
    

    [第八步] 关键代码实现

    图片的编码和解码,常规的代码实现是:
    
    BitmapFactory.decodeXXXX(解码)
    bitmap.compress(format, 75, fos)(编码)
    
    webp的解码实现:
    
    private Bitmap decodeWebp() {
        @SuppressLint("ResourceType") 
        InputStream is = getResources().openRawResource(R.drawable.ceshi);
        byte[] bytes = stream2Bytes(is);
        // 将webp格式的数据转成 argb
        int[] width = new int[1];
        int[] height = new int[1];
        try {
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        byte[] argb = libwebp.WebPDecodeARGB(bytes, bytes.length, width, height);
        // 将argb byte数组转成 int数组
        int[] pixels = new int[argb.length/4];
        ByteBuffer.wrap(argb).asIntBuffer().get(pixels);
        // 获得bitmap
        Bitmap bitmap = Bitmap.createBitmap(pixels, width[0], height[0], Bitmap.Config.ARGB_8888);
        return bitmap;
    }
    
    byte[] stream2Bytes(InputStream is) {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        byte[] buffer = new byte[2048];
        int len;
        try {
            while ((len = is.read(buffer)) != -1) {
                bos.write(buffer,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bos.toByteArray();
    }
    
    webp的编码实现:
    
    
    private void encodeWebp(Bitmap bitmap) {
        // 获取bitmap宽高
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        // 获得bitmap中的ARGB数据nio
        ByteBuffer buffer = ByteBuffer.allocate(bitmap.getByteCount());
        bitmap.copyPixelsToBuffer(buffer);
        // 编码获得webp格式文件数据  4 * width
        byte[] bytes = libwebp.WebPEncodeRGBA(buffer.array(), width, height, width * 4, 75);
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(Environment.getExternalStorageDirectory() + "/libwebp.webp");
            fos.write(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != fos) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

    [本章完...]

    相关文章

      网友评论

          本文标题:性能优化<第十一篇>:webp技术

          本文链接:https://www.haomeiwen.com/subject/lybmultx.html