Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
161 lines (138 sloc) 4.68 KB
#include "compress.h"
typedef u_int8_t BYTE;
#define true 1
#define false 0
struct my_error_mgr {
struct jpeg_error_mgr pub;
jmp_buf setjmp_buffer;
};
typedef struct my_error_mgr *my_error_ptr;
METHODDEF(void)
my_error_exit(j_common_ptr cinfo) {
my_error_ptr myerr = (my_error_ptr) cinfo->err;
(*cinfo->err->output_message)(cinfo);
LOGW("jpeg_message_table[%d]:%s",
myerr->pub.msg_code, myerr->pub.jpeg_message_table[myerr->pub.msg_code]);
longjmp(myerr->setjmp_buffer, 1);
}
int generateJPEG(BYTE *data, int w, int h, jint quality, const char *name, boolean optimize);
const char *jstringToString(JNIEnv *env, jstring jstr);
JNIEXPORT jboolean JNICALL
Java_cn_cfanr_compress_ImageCompress_compressBitmap(JNIEnv *env, jclass type, jobject bitmap,
jstring dstPath_, jint quality,
jboolean isOptimize) {
AndroidBitmapInfo androidBitmapInfo;
BYTE *pixelsColor;
int ret;
BYTE *data;
BYTE *tmpData;
const char *dstFileName = jstringToString(env, dstPath_);
//解码Android Bitmap信息
if ((ret = AndroidBitmap_getInfo(env, bitmap, &androidBitmapInfo)) < 0) {
LOGD("AndroidBitmap_getInfo() failed error=%d", ret);
return false;
}
if ((ret = AndroidBitmap_lockPixels(env, bitmap, (void **)&pixelsColor)) < 0) {
LOGD("AndroidBitmap_lockPixels() failed error=%d", ret);
return false;
}
LOGD("bitmap: width=%d,height=%d,size=%d , format=%d ",
androidBitmapInfo.width, androidBitmapInfo.height,
androidBitmapInfo.height * androidBitmapInfo.width,
androidBitmapInfo.format);
BYTE r, g, b;
int color;
int w, h, format;
w = androidBitmapInfo.width;
h = androidBitmapInfo.height;
format = androidBitmapInfo.format;
data = (BYTE *) malloc(androidBitmapInfo.width * androidBitmapInfo.height * 3);
tmpData = data;
// 将bitmap转换为rgb数据
for (int i = 0; i < h; ++i) {
for (int j = 0; j < w; ++j) {
//只处理 RGBA_8888
if (format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
color = (*(int *) (pixelsColor));
// 这里取到的颜色对应的 A B G R 各占8位
b = (color >> 16) & 0xFF;
g = (color >> 8) & 0xFF;
r = (color >> 0) & 0xFF;
*data = r;
*(data + 1) = g;
*(data + 2) = b;
data += 3;
pixelsColor += 4;
} else {
return -2;
}
}
}
AndroidBitmap_unlockPixels(env, bitmap);
//进行压缩
ret = generateJPEG(tmpData, w, h, quality, dstFileName, isOptimize);
free((void *) dstFileName);
free((void *) tmpData);
return true;
}
int generateJPEG(BYTE *data, int w, int h, int quality, const char *name, boolean optimize) {
int nComponent = 3;
struct jpeg_compress_struct jcs;
//自定义的error
struct my_error_mgr jem;
jcs.err = jpeg_std_error(&jem.pub);
jem.pub.error_exit = my_error_exit;
if (setjmp(jem.setjmp_buffer)) {
return 0;
}
//为JPEG对象分配空间并初始化
jpeg_create_compress(&jcs);
//获取文件信息
FILE *f = fopen(name, "wb");
if (f == NULL) {
return 0;
}
//指定压缩数据源
jpeg_stdio_dest(&jcs, f);
jcs.image_width = w;
jcs.image_height = h;
jcs.arith_code = false;
jcs.input_components = nComponent;
jcs.in_color_space = JCS_RGB;
jpeg_set_defaults(&jcs);
jcs.optimize_coding = optimize;
//为压缩设定参数,包括图像大小,颜色空间
jpeg_set_quality(&jcs, quality, true);
//开始压缩
jpeg_start_compress(&jcs, true);
JSAMPROW row_point[1];
int row_stride;
row_stride = jcs.image_width * nComponent;
while (jcs.next_scanline < jcs.image_height) {
row_point[0] = &data[jcs.next_scanline * row_stride];
jpeg_write_scanlines(&jcs, row_point, 1);
}
if (jcs.optimize_coding) {
LOGI("使用了哈夫曼算法完成压缩");
} else {
LOGI("未使用哈夫曼算法");
}
//压缩完毕
jpeg_finish_compress(&jcs);
//释放资源
jpeg_destroy_compress(&jcs);
fclose(f);
return 1;
}
const char *jstringToString(JNIEnv *env, jstring jstr) {
char *ret;
const char *tempStr = (*env)->GetStringUTFChars(env, jstr, NULL);
jsize len = (*env)->GetStringUTFLength(env, jstr);
if (len > 0) {
ret = (char *) malloc(len + 1);
memcpy(ret, tempStr, len);
ret[len] = 0;
}
(*env)->ReleaseStringUTFChars(env, jstr, tempStr);
return ret;
}