Android使用huffman编码进行图片压缩

高版本(7.0以上)的系统基本不用考虑,貌似Android已经改进了成高压缩比的。期间借用了不少网络资源,在此表示感谢。

因为Android设备的参差不齐,系统API在图片压缩的实现时,为考虑兼容低性能设备,放弃使用了huffman编码对对图片进行压缩,代而取之使用skia引擎。以前深入看了些里边的东西,没有实际使用也就没有深究了,如果需要网络收集大量图片,并存放于个人PC,拟来实现以下这个东西。

libjpeg在Android源码的位置:\external\jpeg

为不额外增加so库的大小,就不另行编译了,此处直接使用androiod系统的so库。

从上述文件件将需要的头文件拷贝过来放在jni文件夹下(做设备开发,使用的版本比较老,EC)

写mk文件,主要内容:

LOCAL_PATH := $(call my-dir)


include $(CLEAR_VARS)

LOCAL_MODULE    := jemen
LOCAL_SRC_FILES := jemen.cpp
LOCAL_LDLIBS :=-llog -ljpeg -ljnigraphics
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_CFLAGS += -O3 -fstrict-aliasing
LOCAL_CFLAGS += -DUSE_ANDROID_ASHMEM
LOCAL_CFLAGS += -DAVOID_TABLES
LOCAL_CFLAGS += -DANDROID_TILE_BASED_DECODE
LOCAL_SDK_VERSION := 19
include $(BUILD_SHARED_LIBRARY)

刚开始好像遇到了找不到so的问题,从网上找资料,弄一个(编译好的系统或者设备的/system/lib里边都有)放在NDK的toolchane目录。根据版本选择,此处放在D:\software\android-ndk-r10e\toolchains\arm-linux-androideabi-4.8\prebuilt\windows-x86_64\lib\gcc\arm-linux-androideabi\4.8。

然后写C代码,主要的函数有:
//声明一些在压缩时需要的变量,jerr用于错误控制
    struct jpeg_compress_struct cinfo;
    struct jpeg_error_mgr jerr;
    cinfo.err = jpeg_std_error(&jerr);
    jerr.output_message=android_output_message;  //使用自定义的日志输出函数,不是必须的
    jerr.error_exit=myjpeg_error_exit;  //使用自定义的错误退出函数,不是必须的
    jpeg_create_compress(&cinfo);  //创建libjpeg的压缩结构体    cinfo.image_width = width;  //设置被压缩图片的宽、高、通道数和色彩空间
    cinfo.image_height = height;
    cinfo.input_components = 3;
    cinfo.in_color_space = JCS_RGB;
    FILE * outfile;  //创建文件变量用于指定压缩数据的输出目标
    if ((outfile = fopen(imgPath, "wb")) == NULL) {
        fprintf(stderr, "can't open %s\n", imgPath);
        exit(1);
    }
    jpeg_set_defaults(&cinfo);  //对cinfo做一些默认设置
    jpeg_stdio_dest(&cinfo, outfile);  //将之前的outfile作为输出目标
    jpeg_set_quality(&cinfo,quality,TRUE);  //设置压缩jpeg图片的质量
    jpeg_start_compress(&cinfo, TRUE);  //开始压缩
    unsigned char * srcImg=(unsigned char *)imageData;  //逐行的获取图像数据,进行压缩处理
    while (cinfo.next_scanline < cinfo.image_height) {
        JSAMPROW row_pointer[1];    /* pointer to JSAMPLE row[s] */
        row_pointer[0] = srcImg;
        (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
        srcImg+=widthStep;
    }
//压缩保存完毕,对使用到的变量进行销毁
    jpeg_finish_compress(&cinfo);
    jpeg_destroy_compress(&cinfo);

然后build,即可成功,这样出来的so只有13,468bytes,不错。

 

2019.8.1日实验,发现与Bitmap.compress相比,在此压缩jpeg图片,并没有更小,有点反而更大???

换用他人的ligjpeg库,发现比原声API压缩的略微小一点点。411885和410335的区别。难道4.4的系统已经采用了huffman编码?

程序中已经显示得将cinfo.arith_code=false;//false代表huffman

 

 

你可能感兴趣的:(Android使用huffman编码进行图片压缩)