前言:
在上一篇文章中,已经编译好可行性文件了,那么接下来配置好Cmake,废话不多说了,直接撸码...
Step1:新建一个NDK工程
Window平台NDK版本:android-ndk-r19c
Android Studio:3.4
Step2:复制相关文件到AS工程
项目结构.png备注:相关文件会上传到github上
CMakeLists.txt:
cmake_minimum_required(VERSION 3.4.1)
#set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})
add_library( # Sets the name of the library.
compress-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
native-lib.cpp )
#STATIC
add_library(libjpeg STATIC IMPORTED)
set_target_properties(libjpeg PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libs/armeabi-v7a/libturbojpeg.a)
#引入头文件 import
include_directories(${CMAKE_SOURCE_DIR}/include)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__STDC_CONSTANT_MACROS -L${CMAKE_SOURCE_DIR}/libs/armeabi-v7a")
target_link_libraries( # Specifies the target library.
compress-lib
libjpeg
#jnigraphics是安卓NDK目录中直接有的
jnigraphics
# Links the target library to the log library
# included in the NDK.
log )
build.grade(app):
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
buildToolsVersion "29.0.0"
defaultConfig {
applicationId "com.chen.libjpegcompress"
minSdkVersion 18
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
abiFilters 'armeabi-v7a'
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.10.2"
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation project(path: ':compress')
implementation 'com.github.bumptech.glide:glide:4.9.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
api 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.3@aar'
api 'io.reactivex.rxjava2:rxandroid:2.0.1'
api 'io.reactivex.rxjava2:rxjava:2.0.5'
}
Step3:压缩原理
参考:https://www.jianshu.com/p/097f4486f3e6
参考:https://www.jianshu.com/p/eebe2107da6d
Step4:C++代码实现压缩
extern "C"
JNIEXPORT void JNICALL
Java_com_chen_compress_CompressUtils_nativeCompress(JNIEnv *env, jobject instance,
jobject bitmap, jint q, jstring path_) {
const char *path = env->GetStringUTFChars(path_, 0);
jclass jclazz = env->GetObjectClass(instance);
jmethodID onCompleteListenerId = env->GetMethodID(jclazz, "onCompleteListener", "()V");
jmethodID onStartListenerId = env->GetMethodID(jclazz, "onStartListener", "()V");
env->CallVoidMethod(instance, onStartListenerId);
//从bitmap获取argb数据
AndroidBitmapInfo info;//info=new 对象();
//获取里面的信息
AndroidBitmap_getInfo(env, bitmap, &info);// void method(list)
//得到图片中的像素信息
uint8_t *pixels;//uint8_t char java byte *pixels可以当byte[]
AndroidBitmap_lockPixels(env, bitmap, (void **) &pixels);
//jpeg argb中去掉他的a ===>rgb
int w = info.width;
int h = info.height;
int color;
//开一块内存用来存入rgb信息
uint8_t *data = (uint8_t *) malloc(w * h * 3);//data中可以存放图片的所有内容
uint8_t *temp = data;
uint8_t r, g, b;//byte
//循环取图片的每一个像素
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
color = *(int *) pixels;//0-3字节 color4 个字节 一个点
//取出rgb
r = (color >> 16) & 0xFF;// #00rrggbb 16 0000rr 8 00rrgg
g = (color >> 8) & 0xFF;
b = color & 0xFF;
//存放,以前的主流格式jpeg bgr
*data = b;
*(data + 1) = g;
*(data + 2) = r;
data += 3;
//指针跳过4个字节
pixels += 4;
}
}
//把得到的新的图片的信息存入一个新文件 中
write_JPEG_file(temp, w, h, q, path);
env->CallVoidMethod(instance, onCompleteListenerId);
//释放内存
free(temp);
AndroidBitmap_unlockPixels(env, bitmap);
env->ReleaseStringUTFChars(path_, path);
}
void write_JPEG_file(uint8_t *data, int w, int h, jint q, const char *path) {
// 3.1、创建jpeg压缩对象
jpeg_compress_struct jcs;
//错误回调
jpeg_error_mgr error;
jcs.err = jpeg_std_error(&error);
//创建压缩对象
jpeg_create_compress(&jcs);
// 3.2、指定存储文件 write binary
FILE *f = fopen(path, "wb");
jpeg_stdio_dest(&jcs, f);
// 3.3、设置压缩参数
jcs.image_width = w;
jcs.image_height = h;
//bgr
jcs.input_components = 3;
jcs.in_color_space = JCS_RGB;
jpeg_set_defaults(&jcs);
//开启哈夫曼功能
jcs.optimize_coding = true;
jpeg_set_quality(&jcs, q, 1);
// 3.4、开始压缩
jpeg_start_compress(&jcs, 1);
// 3.5、循环写入每一行数据
int row_stride = w * 3;//一行的字节数
JSAMPROW row[1];
while (jcs.next_scanline < jcs.image_height) {
//取一行数据
uint8_t *pixels = data + jcs.next_scanline * row_stride;
row[0]=pixels;
jpeg_write_scanlines(&jcs,row,1);
}
// 3.6、压缩完成
jpeg_finish_compress(&jcs);
// 3.7、释放jpeg对象
fclose(f);
jpeg_destroy_compress(&jcs);
}
Step5:效果图 压缩效果图.jpg
备注:原图2.8M 压缩后图片401kb
好了,效果达到了。
github:https://github.com/MrRightChen/LibJpegCompress。还有SDK制作,敬请期待!
网友评论