高版本(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