一.理论基础
android 使用Skia图像处理引擎,skia引擎基于jpeg引擎二次开发而来(类似于retrofit 与okhttp的关系)。jpeg引擎提供两种图片压缩编码(普通优化编码和哈夫曼编码)
注意:android 7.0 Skia引擎写死了是普通优化编码,在7.0以后,才可以选择哈夫曼编码。
二.哈夫曼编码
可变长编码(节约内存),根据频率越高,位数越短。
三.效果对比
image.png四.代码
public void onLoad(View view) {
File input = new File(Environment.getExternalStorageDirectory()
, "main.jpg");
Bitmap inputBitmap = BitmapFactory.decodeFile(input.getAbsolutePath());
File output= new File(Environment.getExternalStorageDirectory(),
"微信压缩.jpg");
compress(inputBitmap, output.getAbsolutePath());
}
typedef uint8_t BYTE;
extern "C"{
#include "jpeglib.h"
}
//jpeg 引擎
void writeImg(BYTE *data, const char *path, int w, int h) {
struct jpeg_compress_struct jpeg_struct;
jpeg_error_mgr err;
jpeg_struct.err= jpeg_std_error(&err);
jpeg_create_compress(&jpeg_struct);
FILE *file = fopen(path, "wb");
jpeg_stdio_dest(&jpeg_struct, file);
jpeg_struct.image_width = w;
jpeg_struct.image_height = h;
jpeg_struct.input_components = 3;
jpeg_struct.in_color_space = JCS_RGB;
//核心 /* TRUE=arithmetic coding, FALSE=Huffman */
jpeg_struct.arith_code = FALSE;
jpeg_set_defaults(&jpeg_struct);
jpeg_set_quality(&jpeg_struct, 30, true);
//开启压缩
jpeg_start_compress(&jpeg_struct, TRUE);
JSAMPROW row_pointer[1];
while (jpeg_struct.next_scanline < h) {
row_pointer[0]= &data[jpeg_struct.next_scanline * w * 3];
jpeg_write_scanlines(&jpeg_struct,row_pointer,1);
}
jpeg_finish_compress(&jpeg_struct);
fclose(file);
jpeg_destroy_compress(&jpeg_struct);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_luisliuyi_demo_optimize_bitmap02_MainActivity_compress(JNIEnv *env, jobject thiz,
jobject bitmap,
jstring path_) {
const char *path = env->GetStringUTFChars(path_, 0);
AndroidBitmapInfo bitmapInfo;
AndroidBitmap_getInfo(env, bitmap, &bitmapInfo);
int h = bitmapInfo.height;
int w = bitmapInfo.width;
BYTE *pixels;
AndroidBitmap_lockPixels(env, bitmap, reinterpret_cast<void **>(&pixels));
BYTE *data,*tmpData;
data = static_cast<BYTE *>(malloc(w * h * 3));
tmpData = data;
BYTE a, r, g, b;
int color;
for (int i = 0; i < h; ++i) {
for (int j = 0; j < w; ++j) {
color = *((int *) pixels);
a = ((color & 0xFF000000) >> 16);
r = ((color & 0x00FF0000) >> 16);
g = ((color & 0x0000FF00) >> 8);
b = (color & 0x000000FF);
*data = b;
*(data + 1) = g;
*(data + 2) = r;
data += 3;
pixels += 4;
}
}
writeImg(tmpData, path, w, h);
AndroidBitmap_unlockPixels(env, bitmap);
env->ReleaseStringUTFChars(path_, path);
}
五.结果
image.png六.代码地址
https://gitee.com/luisliuyi/android-optimize-bitmap02.git
网友评论