首先去这个地址下载:
https://github.com/bither/bither-android-lib
解压获取这个libjpeg-turbo文件的文件,里面只留jni文件夹,其他全部删除,
之后进行编译libjpeg.so包,编译的时候先要进入到jni文件夹里面,执行下面命令
命令:ndk-build APP_ABI=armeabi-v7a,armeabi
编译成功之后会在jni同级目录生成libs和obj,编译好的包就在libs里面
前提:要配置好ndk-build的全局变量
在编译的时候环境出现了一系列不可描述的问题,最后我就用了android-ndk-r11c这个环境的ndk,可以用上面的命令直接编译出so包
1.新建一个module,将刚刚编译出来的armeabi-v7a和armeabi 文件夹复制进libs,里面出了libjpeg.so,其他文件可以不要
2.去刚刚下载的libjpeg-trubo文件里面的jni文件夹里面复制头文件进入,可以用*.h过滤出来,然后全部复制进去
3.配置CMaketList.txt
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
#设置生成的so动态库最后输出的路径
#SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/libs/${ANDROID_ABI})
#指定要引用的libjpeg.so的头文件目录
INCLUDE_DIRECTORIES(
src/main/cpp/include
)
#静态引入libjpeg
ADD_LIBRARY(jpeg STATIC IMPORTED)
#对应so目录
SET_TARGET_PROPERTIES(jpeg PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/libs/${ANDROID_ABI}/libjpeg.so)
#动态引入C++
ADD_LIBRARY(
jpegjni
SHARED
src/main/cpp/jpegjni.cpp
)
FIND_LIBRARY(graphics jnigraphics)
FIND_LIBRARY(log-lib log)
#设置库的名称
TARGET_LINK_LIBRARIES(jpegjni jpeg ${log-lib} ${graphics})
其实so动态库的输出文件路径不设置也可以的,最后打包还是会包含进apk里面
问题:
error: undefined reference to 'jpeg_std_error(jpeg_error_mgr*)
解决:
extern "C" {
#include <jpeglib.h>
}
java文件:
public class ImageLib {
static {
System.loadLibrary("jpegjni");
}
public static native String compressBitmap(Bitmap bit, int w, int h, int quality, byte[] fileNameBytes, boolean optimize);
}
头文件:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_kawa_jpeglib_utils_ImageLib */
#ifndef _Included_com_kawa_jpeglib_utils_ImageLib
#define _Included_com_kawa_jpeglib_utils_ImageLib
#ifdef __cplusplus
extern "C" {
#include <setjmp.h>
#include <jpeglib.h>
#include <android/bitmap.h>
#endif
/*
* Class: com_kawa_jpeglib_utils_ImageLib
* Method: compressBitmap
* Signature: (Landroid/graphics/Bitmap;III[BZ)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_kawa_jpeglib_utils_ImageLib_compressBitmap
(JNIEnv *,jclass, jobject, jint, jint, jint, jbyteArray, jboolean);
#ifdef __cplusplus
}
#endif
#endif
C++文件:
//
// Created by Kawa on 2018/7/16.
//
#include <string.h>
#include <android/log.h>
#include <setjmp.h>
#include <malloc.h>
#include "com_kawa_jpeglib_utils_ImageLib.h"
#define LOG_TAG "jni"
#define LOGW(...) __android_log_write(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
#define true 1
#define false 0
typedef uint8_t BYTE;
char *error;
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);
// error = myerr->pub.jpeg_message_table[myerr->pub.msg_code];
LOGE("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, int quality,
const char *outfilename, jboolean optimize) {
int nComponent = 3;
struct jpeg_compress_struct jcs;
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_create_compress(&jcs);
FILE *f = fopen(outfilename, "wb");
if (f == NULL) {
return 0;
}
jpeg_stdio_dest(&jcs, f);
jcs.image_width = w;
jcs.image_height = h;
if (optimize) {
LOGI("optimize==ture");
} else {
LOGI("optimize==false");
}
jcs.arith_code = false;
jcs.input_components = nComponent;
if (nComponent == 1)
jcs.in_color_space = JCS_GRAYSCALE;
else
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_pointer[1];
int row_stride;
row_stride = jcs.image_width * nComponent;
while (jcs.next_scanline < jcs.image_height) {
row_pointer[0] = &data[jcs.next_scanline * row_stride];
jpeg_write_scanlines(&jcs, row_pointer, 1);
}
if (jcs.optimize_coding) {
LOGI("optimize==ture");
} else {
LOGI("optimize==false");
}
jpeg_finish_compress(&jcs);
jpeg_destroy_compress(&jcs);
fclose(f);
return 1;
}
typedef struct {
uint8_t r;
uint8_t g;
uint8_t b;
} rgb;
char *jstrinTostring(JNIEnv *env, jbyteArray barr) {
char *rtn = NULL;
jsize alen = env->GetArrayLength(barr);
jbyte *ba = env->GetByteArrayElements(barr, 0);
if (alen > 0) {
rtn = (char *) malloc(alen + 1);
memcpy(rtn, ba, alen);
rtn[alen] = 0;
}
env->ReleaseByteArrayElements(barr, ba, 0);
return rtn;
}
jstring Java_com_kawa_jpeglib_utils_ImageLib_compressBitmap(JNIEnv *env,
jclass thiz, jobject bitmapcolor,
jint w, jint h, jint quality,
jbyteArray fileNameStr,
jboolean optimize) {
AndroidBitmapInfo infocolor;
BYTE *pixelscolor;
int ret;
BYTE *data;
BYTE *tmpdata;
char *fileName = jstrinTostring(env, fileNameStr);
if ((ret = AndroidBitmap_getInfo(env, bitmapcolor, &infocolor)) < 0) {
LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
return env->NewStringUTF("0");;
}
if ((ret = AndroidBitmap_lockPixels(env, bitmapcolor, (void **) &pixelscolor)) < 0) {
LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
}
BYTE r, g, b;
data = NULL;
data = (BYTE *) (malloc(w * h * 3));
tmpdata = data;
int j = 0, i = 0;
int color;
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
color = *((int *) pixelscolor);
r = ((color & 0x00FF0000) >> 16);
g = ((color & 0x0000FF00) >> 8);
b = color & 0x000000FF;
*data = b;
*(data + 1) = g;
*(data + 2) = r;
data = data + 3;
pixelscolor += 4;
}
}
AndroidBitmap_unlockPixels(env, bitmapcolor);
int resultCode = generateJPEG(tmpdata, w, h, quality, fileName, optimize);
free(tmpdata);
if (resultCode == 0) {
jstring result = env->NewStringUTF(error);
error = NULL;
return result;
}
return env->NewStringUTF("1"); //success
}
build.gradle文件:
apply plugin: 'com.android.library'
android {
compileSdkVersion 25
buildToolsVersion '27.0.3'
defaultConfig {
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
externalNativeBuild {
cmake {
cppFlags ""
arguments '-DANDROID_PLATFORM=android-23',
'-DANDROID_TOOLCHAIN=clang', '-DANDROID_STL=gnustl_static'
}
}
ndk {
abiFilters "armeabi-v7a", "armeabi"
}
}
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
api 'com.android.support:appcompat-v7:25.3.1'
}
app项目引用: implementation project(':jpeglib')
jpeglib是刚刚的模块的名字