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

原创 2016年08月29日 02:24:23
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:源码

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

动脑学院课程视频性能优化,移动框架,高级UI,NDK

动脑学院安卓的VIP教程视频包括(性能优化,移动框架,高级UI,DNK) 在某宝购买的...

动脑学院安卓视频资料领取

采取百度云链接的方式分享出来 希望为更多有需要的老铁带来点点暖意 系统服务杀得死吗?系统服务守护启示录-ndk层实现双进程守护 链接:http://pan.baidu.com/s/1i5w0Xd...

动脑学院听课笔记-缓存那些事20170622

缓存击穿和缓存雪崩解决办法 Hash函数

关于切换自定义组件(Button,CheckBox,EditText)被点击或选中时背景的方法

。 当我们觉得某些组件的样式 不给力的时候(比如Button,CheckBox,EditText),就会想到给这些组件自定义样式了,这里提供简单的两种方法: 一、改背景 比如说Button,...

Activity,Fragment的基类封装,简化findViewById,Fragment懒加载和不重复加载等

有想到的再继续更新,也希望你们可以分享给我. 下面的复制即可使用 Activitypublic class BaseActivity extends AppCompatActivity { ...

svg矢量图实现android多形状图形框架-动脑学院

位图:可以看到像素点 png jpg… 矢量图:算法生成的 依据路径 SVG:SVG 是使用 XML 来描述二维图形和绘图程序的语言。矩形: ...

动脑学院高级ui效果之水波纹

水波纹动画展示效果: 针对于这样的效果我们可能想起来的绘制方式有: 第一种方式: 正弦曲线  计算x,y。VauleAnimation  控制x的行走画无数个直线–利用高等数学微积分path...

nodejs+grunt基础【动脑学院】

  • 2017年03月19日 10:11
  • 32B
  • 下载

SSH 框架学习之初识Java中的Action、Dao、Service、Model—————————–学到就要查,自己动手动脑!!!

SSH 框架学习之初识Java中的Action、Dao、Service、Model—————————–学到就要查,自己动手动脑!!!    基础知识目前不够,有感性认识即可 首先这是现在最基本的...
  • wjlgdut
  • wjlgdut
  • 2017年06月05日 16:52
  • 202

[Android]-图片JNI(C++\Java)高斯模糊的实现与比较

Android:使用JNI与使用Java方式进行图片高斯模糊的比较。
  • qiujuer
  • qiujuer
  • 2014年04月22日 00:03
  • 7415
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:动脑学院 - Java 和 JNI方式处理图片比较
举报原因:
原因补充:

(最多只允许输入30个字)