Permalink
Cannot retrieve contributors at this time
#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; | |
} |