Android libjpeg图片压缩模块

首页去这个地址:

git clone git://git.linaro.org/people/tomgall/libjpeg-turbo/libjpeg-turbo.git

libjpeg-trubo Android 版拉取到本地,之后进行编译libjpeg.so包

命令:ndk-build APP_ABI=armeabi-v7a,armeabi 

前提:要配置好ndk-build的全局变量

在编译的时候环境出现了一系列不可描述的问题,最后我就用了android-ndk-r11c这个环境的ndk,可以用上面的命令直接编译出so包

下面开始封装模块

1.新建一个module,将刚刚编译出来的armeabi-v7a和armeabi 文件夹复制进libs,里面出了libjpeg.so,其他文件可以不要

2.去刚刚下载的libjpeg-trubo里面复制头文件进入,可以用*.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是刚刚的模块的名字


猜你喜欢

转载自blog.csdn.net/u014476720/article/details/81064205