您的位置:首页 > 编程语言 > Java开发

动脑学院 - Java 和 JNI方式处理图片比较

2016-08-29 02:24 351 查看
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)。

Github:源码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  图片 jni java android