【第21期】观点:人工智能到底用 GPU?还是用 FPGA?

动脑学院 - 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:源码

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

相关文章推荐

NDK开发基础①使用Android Studio编写NDK

NDK开发基础①使用Android Studio编写NDK

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

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

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

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

Android进阶——MVP从入门到进阶

1.定义MVP的全称为Model-View-Presenter,即模型-视图-协调器(主持者)Model:处理数据和业务逻辑等,如:数据库的操作,数据的请求,数据运算,JavaBean; View:显...
  • wo_ha
  • wo_ha
  • 2017-03-01 15:10
  • 358

动脑学院学习笔记-EventBus 3.0核心原理,打造事件分发框架

EventBus 解决消息事件传递,线程切换问题。订阅者模式,核心也是Hander机制。3.0加入注解,通过注册类的注解 RxBus是一个设计模式,核心原理是RxJava,链式调度,事件变换...

让我们自己的Android程序可以自动后台升级的实现(需Root权限)

首先分析如何才能让我们的应用程序才能后台安装APK——获取Root权限使用命令安装,这个问题解决了只能说实现了一般,那么怎样才能实现自己安装自己,最开始的想法是在在下载升级程序包后自己调用命令安装,但...
  • wo_ha
  • wo_ha
  • 2016-12-07 17:04
  • 590

mybatis入门篇

基础知识 对原生jdbc程序(单独使用jdbc开发)问题总结 mybatis框架原理 mybatis入门程序(用户的增删改查) mybatis开发dao两种方法:     原始dao开发方法(程序需要...

学习

学号16340209 [本人学院:数据科学与计算机学院](http://sdcs.sysu.edu.cn/) ----- **目录** **1.前言导论** ====================...

理解专业程序员

铁文整理   理解专业程序员 Understanding the Professional Programmer ...
  • tiewen
  • tiewen
  • 2014-11-21 10:36
  • 3376
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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