MainAcitivty:
/**
* @projectName:JavaNdkComp
* @fileName:MainActivity.java
* @packageName:club.younge.demo
* @date:2016年8月28日下午11:10:29
* @copyright (c) 2016, heqy@finansir.nt All Rights Reserved.
*
*/
package club.younge.demo;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap.Config;
import android.media.Image;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;
import club.younge.java.JavaImageUtils;
import club.younge.ndk.NdkImageUtils;
/**
* @className:MainActivity
* @function: TODO ADD FUNCTION.
* @reason: TODO ADD REASON.
* @date: 2016年8月28日 下午11:10:29
* @author Younge
* @version
* @since JDK 1.8
* @see
*/
public class MainActivity extends Activity {
private ImageView imageView;
private Bitmap mBitmap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
imageView = (ImageView) findViewById(R.id.imageView);
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.xy);
}
public void srcImage(View view) {
imageView.setImageBitmap(mBitmap);
}
public void javaImage(View view) {
long start = System.currentTimeMillis();
Bitmap bitmap = JavaImageUtils.getBitMap(mBitmap);
imageView.setImageBitmap(bitmap);
long end = System.currentTimeMillis();
Toast.makeText(this, "耗时:"+ (end -start) +"ms", Toast.LENGTH_SHORT).show();
}
public void ndkImage(View view) {
int width = mBitmap.getWidth();
int height = mBitmap.getHeight();
int[] buffer = new int[width*height];
mBitmap.getPixels(buffer, 0, width, 0, 0, width, height);
long start = System.currentTimeMillis();
int[] result = NdkImageUtils.getImage(buffer, width, height);
Bitmap bitmap = Bitmap.createBitmap(result, 0, width, width, height, Config.ARGB_8888);
imageView.setImageBitmap(bitmap);
long end = System.currentTimeMillis();
Toast.makeText(this, "耗时:"+ (end -start) +"ms", Toast.LENGTH_SHORT).show();
}
}
JavaImageUtils:
/**
* @projectName:JavaNdkComp
* @fileName:JavaImageUtils.java
* @packageName:club.younge.java
* @date:2016年8月28日下午11:12:57
* @copyright (c) 2016, heqy@finansir.nt All Rights Reserved.
*
*/
package club.younge.java;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Color;
/**
* @className:JavaImageUtils
* @function: TODO ADD FUNCTION.
* @reason: TODO ADD REASON.
* @date: 2016年8月28日 下午11:12:57
* @author Younge
* @version
* @since JDK 1.8
* @see
*/
public class JavaImageUtils {
public static Bitmap getBitMap(Bitmap bitmap){
if(bitmap == null) return null;
int width = bitmap.getWidth();
int height = bitmap.getHeight();
Bitmap result = Bitmap.createBitmap(width, height, Config.ARGB_8888);
int color, a, r, g, b, rt, gt, bt;
float bright = 0.2f;
float contrast = 0.2f;
int bri = (int)(256*bright);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
color = bitmap.getPixel(x, y);
a = Color.alpha(color);
r = Color.red(color);
g = Color.green(color);
b = Color.blue(color);
//更改亮度,统一增加一个值,变得更白更亮
rt = r + bri;
gt = g + bri;
bt = b + bri;
r = rt > 255 ? 255:(rt < 0 ? 0: rt); //事实在目前情况下,不会出现rt小于0的情况,此处这么写是为了统一后边
g = gt > 255 ? 255:(gt < 0 ? 0: gt);
b = bt > 255 ? 255:(bt < 0 ? 0: bt);
//更改对比度, 以128中间值为分界点,白的更白,黑的更黑,增加对比度
r = r - 128;
g = g - 128;
b = b - 128;
rt = (int) (r*(1 + contrast)) + 128;
gt = (int) (g*(1 + contrast)) + 128;
bt = (int) (b*(1 + contrast)) + 128;
r = rt > 255 ? 255:(rt < 0 ? 0: rt);
g = gt > 255 ? 255:(gt < 0 ? 0: gt);
b = bt > 255 ? 255:(bt < 0 ? 0: bt);
color = Color.argb(a, r, g, b);
result.setPixel(x, y, color);
}
}
return result;
}
}
NdkImageUtils:
/**
* @projectName:JavaNdkComp
* @fileName:NdkImageUtils.java
* @packageName:club.younge.ndk
* @date:2016年8月28日下午11:13:12
* @copyright (c) 2016, heqy@finansir.nt All Rights Reserved.
*
*/
package club.younge.ndk;
/**
* @className:NdkImageUtils
* @function: TODO ADD FUNCTION.
* @reason: TODO ADD REASON.
* @date: 2016年8月28日 下午11:13:12
* @author Younge
* @version
* @since JDK 1.8
* @see
*/
public class NdkImageUtils {
static{
System.loadLibrary("Image");
}
public static native int[] getImage(int[] buffer, int width, int height);
}
生成的JNI头文件,club_younge_ndk_NdkImageUtils.h:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class club_younge_ndk_NdkImageUtils */
#ifndef _Included_club_younge_ndk_NdkImageUtils
#define _Included_club_younge_ndk_NdkImageUtils
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: club_younge_ndk_NdkImageUtils
* Method: getImage
* Signature: ([III)[I
*/
JNIEXPORT jintArray JNICALL Java_club_younge_ndk_NdkImageUtils_getImage
(JNIEnv *, jclass, jintArray, jint, jint);
#ifdef __cplusplus
}
#endif
#endif
实现类,编辑实现类时,右键,Android tools -> add Native support, 然后右键Properties -> c/c++ general -> paths and symbols 若为添加包含的头文件路径,需要添加包含的头文件路径,这样在CPP文件中才会出现代码提示,确保不那么容易出现错误。club_younge_ndk_NdkImageUtils.cpp:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <stdlib.h>
#include <jni.h>
#include "club_younge_ndk_NdkImageUtils.h"
/* Header for class club_younge_ndk_NdkImageUtils */
/*
* Class: club_younge_ndk_NdkImageUtils
* Method: getImage
* Signature: ([III)[I
*/
JNIEXPORT jintArray JNICALL Java_club_younge_ndk_NdkImageUtils_getImage
(JNIEnv *env, jclass clazz, jintArray buffer, jint width, jint height){
jint *buf = (jint*)env->GetIntArrayElements(buffer, 0);
jsize len = env->GetArrayLength(buffer);
jint resultBuf[len];
jintArray result = env->NewIntArray(len);
int color, a, r, g, b, rt, gt, bt;
int bright = (int)(0.2f*256);
float contrast = 0.2f;
for(int x = 0; x < width; x++){
for(int y = 0; y < height; y++){
color = buf[y*width + x];
a = color >> 24;
r = (color >> 16) & 0xFF;
g = (color >> 8) & 0xFF;
b = color & 0xFF;
//改变亮度
rt = r + bright;
gt = g + bright;
bt = b + bright;
r = rt > 255 ? 255 : rt;
g = gt > 255 ? 255 : gt;
b = bt > 255 ? 255 : bt;
//改变对比度
r = r - 128;
g = g - 128;
b = b - 128;
rt = (int) (r*(1 + contrast)) + 128;
gt = (int) (g*(1 + contrast)) + 128;
bt = (int) (b*(1 + contrast)) + 128;
r = rt > 255 ? 255 : (rt < 0 ? 0 : rt);
g = gt > 255 ? 255 : (gt < 0 ? 0 : gt);
b = bt > 255 ? 255 : (bt < 0 ? 0 : bt);
color = a << 24 | r << 16 | g << 8 | b;
resultBuf[y*width + x] = color;
}
}
env->ReleaseIntArrayElements(buffer,buf,0);
env->SetIntArrayRegion(result, 0, len, resultBuf);
return result;
}
测试结果:java:1579ms, jni:470ms, 性能提升3倍多一点。若用大图超过1M,JNI调用直接崩溃退出,报Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1)。