Android 使用NDK处理BItmap及如何通过C/C++直接控制View的suface显示,学习笔记及方向

最近的学习真的比较困难,因为学习了SDK开发项目后,做了一些简单的项目后,觉得在UI线程中加载较多图片时,总会出现卡顿的感觉,特别是手指滑动下拉时,这种卡顿更易察觉到,而java的结构化开发能力确实是很强大的,使用java开发确实是一件非常享受的事情,但是java在一些高密度的计算中是没有什么优势的,在享受内存自动回收时也会遇到一些不如意的事。任何语言或事物,总会有优缺点,这是java如此简单易用的一个副作用。所以为了不使java的副作用危害到开发者使用java,java产生了一种非常有吸引力的的技术JNI技术,这种技术可以让Java调用C/C++和其他的语言所写的程序。而这种技术也在android中得以支持--NDK, NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk,使用起来非常方便。

说了一堆的废话,接下来记录下自己最近所学习到的东西,可以说NDK重要的学习资料之一就是android的官方网站提供的资料,包括下载了NDK后,也能看到一些简单的使用了NDK的项目源码,这些源码能让我们知道android官方建议我们如何使用NDK,甚至可以用纯C/C++语言开发应用,但这并不是我感兴趣的,具体原因就不说了。

按照官方的使用方式还是比较简单的,这里写了一个用C语言提取照片灰度图的函数,并在java中调用

先写java代码

public class PhotoProcessingActivity extends Activity{

	private Bitmap bmOriginal,bmGray;
	private ImageView iv;
	private Button btGray,btOpen;

	static{
		System.loadLibrary("PhotoProcessing");
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.photo_processing_activity);

		setup();
	}

	public void setup(){
		iv = (ImageView) findViewById(R.id.showPhoto);
		bmOriginal = ImageShare.mBitmap;
		iv.setImageBitmap(bmOriginal);

		btGray = (Button) findViewById(R.id.btGray);
		btGray.setOnClickListener(onclick);
		btOpen = (Button) findViewById(R.id.btOpen);
		btOpen.setOnClickListener(onclick);

	}

	OnClickListener onclick = new OnClickListener(){
		@Override
		public void onClick(View v) {
			// TODO Auto-generated method stub
			switch(v.getId()){
			case R.id.btGray:
				bmGray = Bitmap.createBitmap(bmOriginal.getWidth(), bmOriginal.getHeight(), Config.ALPHA_8);
				grayPhoto(bmOriginal, bmGray);
				iv.setImageBitmap(bmGray);
				break;
			case R.id.btOpen:
				Intent intent = new Intent(PhotoProcessingActivity.this,
						SurfaceProcessingActivity.class);
				startActivity(intent);
				break;
			}
		}
	};

	public native void grayPhoto(Bitmap bmOriginal,Bitmap bmGray);
}

使用javah工具得到头文件PhotoProcessingActivity.h并且添加处理图片所需的一些头文件,这些头文件都是NDK中的include中自带的,使用时可以把把该文件夹链接进去

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_photoprocessing_activity_PhotoProcessingActivity */
#include <android/bitmap.h>
#include <android/log.h>
#include <math.h>
#include <string.h>

#ifndef _Included_com_example_photoprocessing_activity_PhotoProcessingActivity
#define _Included_com_example_photoprocessing_activity_PhotoProcessingActivity
#ifdef __cplusplus
extern "C" {
#endif
#undef com_example_photoprocessing_activity_PhotoProcessingActivity_MODE_PRIVATE
#define com_example_photoprocessing_activity_PhotoProcessingActivity_MODE_PRIVATE 0L
#undef com_example_photoprocessing_activity_PhotoProcessingActivity_MODE_WORLD_READABLE
#define com_example_photoprocessing_activity_PhotoProcessingActivity_MODE_WORLD_READABLE 1L
#undef com_example_photoprocessing_activity_PhotoProcessingActivity_MODE_WORLD_WRITEABLE
#define com_example_photoprocessing_activity_PhotoProcessingActivity_MODE_WORLD_WRITEABLE 2L
#undef com_example_photoprocessing_activity_PhotoProcessingActivity_MODE_APPEND
#define com_example_photoprocessing_activity_PhotoProcessingActivity_MODE_APPEND 32768L
#undef com_example_photoprocessing_activity_PhotoProcessingActivity_MODE_MULTI_PROCESS
#define com_example_photoprocessing_activity_PhotoProcessingActivity_MODE_MULTI_PROCESS 4L
#undef com_example_photoprocessing_activity_PhotoProcessingActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING
#define com_example_photoprocessing_activity_PhotoProcessingActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING 8L
#undef com_example_photoprocessing_activity_PhotoProcessingActivity_BIND_AUTO_CREATE
#define com_example_photoprocessing_activity_PhotoProcessingActivity_BIND_AUTO_CREATE 1L
#undef com_example_photoprocessing_activity_PhotoProcessingActivity_BIND_DEBUG_UNBIND
#define com_example_photoprocessing_activity_PhotoProcessingActivity_BIND_DEBUG_UNBIND 2L
#undef com_example_photoprocessing_activity_PhotoProcessingActivity_BIND_NOT_FOREGROUND
#define com_example_photoprocessing_activity_PhotoProcessingActivity_BIND_NOT_FOREGROUND 4L
#undef com_example_photoprocessing_activity_PhotoProcessingActivity_BIND_ABOVE_CLIENT
#define com_example_photoprocessing_activity_PhotoProcessingActivity_BIND_ABOVE_CLIENT 8L
#undef com_example_photoprocessing_activity_PhotoProcessingActivity_BIND_ALLOW_OOM_MANAGEMENT
#define com_example_photoprocessing_activity_PhotoProcessingActivity_BIND_ALLOW_OOM_MANAGEMENT 16L
#undef com_example_photoprocessing_activity_PhotoProcessingActivity_BIND_WAIVE_PRIORITY
#define com_example_photoprocessing_activity_PhotoProcessingActivity_BIND_WAIVE_PRIORITY 32L
#undef com_example_photoprocessing_activity_PhotoProcessingActivity_BIND_IMPORTANT
#define com_example_photoprocessing_activity_PhotoProcessingActivity_BIND_IMPORTANT 64L
#undef com_example_photoprocessing_activity_PhotoProcessingActivity_BIND_ADJUST_WITH_ACTIVITY
#define com_example_photoprocessing_activity_PhotoProcessingActivity_BIND_ADJUST_WITH_ACTIVITY 128L
#undef com_example_photoprocessing_activity_PhotoProcessingActivity_CONTEXT_INCLUDE_CODE
#define com_example_photoprocessing_activity_PhotoProcessingActivity_CONTEXT_INCLUDE_CODE 1L
#undef com_example_photoprocessing_activity_PhotoProcessingActivity_CONTEXT_IGNORE_SECURITY
#define com_example_photoprocessing_activity_PhotoProcessingActivity_CONTEXT_IGNORE_SECURITY 2L
#undef com_example_photoprocessing_activity_PhotoProcessingActivity_CONTEXT_RESTRICTED
#define com_example_photoprocessing_activity_PhotoProcessingActivity_CONTEXT_RESTRICTED 4L
#undef com_example_photoprocessing_activity_PhotoProcessingActivity_RESULT_CANCELED
#define com_example_photoprocessing_activity_PhotoProcessingActivity_RESULT_CANCELED 0L
#undef com_example_photoprocessing_activity_PhotoProcessingActivity_RESULT_OK
#define com_example_photoprocessing_activity_PhotoProcessingActivity_RESULT_OK -1L
#undef com_example_photoprocessing_activity_PhotoProcessingActivity_RESULT_FIRST_USER
#define com_example_photoprocessing_activity_PhotoProcessingActivity_RESULT_FIRST_USER 1L
#undef com_example_photoprocessing_activity_PhotoProcessingActivity_DEFAULT_KEYS_DISABLE
#define com_example_photoprocessing_activity_PhotoProcessingActivity_DEFAULT_KEYS_DISABLE 0L
#undef com_example_photoprocessing_activity_PhotoProcessingActivity_DEFAULT_KEYS_DIALER
#define com_example_photoprocessing_activity_PhotoProcessingActivity_DEFAULT_KEYS_DIALER 1L
#undef com_example_photoprocessing_activity_PhotoProcessingActivity_DEFAULT_KEYS_SHORTCUT
#define com_example_photoprocessing_activity_PhotoProcessingActivity_DEFAULT_KEYS_SHORTCUT 2L
#undef com_example_photoprocessing_activity_PhotoProcessingActivity_DEFAULT_KEYS_SEARCH_LOCAL
#define com_example_photoprocessing_activity_PhotoProcessingActivity_DEFAULT_KEYS_SEARCH_LOCAL 3L
#undef com_example_photoprocessing_activity_PhotoProcessingActivity_DEFAULT_KEYS_SEARCH_GLOBAL
#define com_example_photoprocessing_activity_PhotoProcessingActivity_DEFAULT_KEYS_SEARCH_GLOBAL 4L
/*
 * Class:     com_example_photoprocessing_activity_PhotoProcessingActivity
 * Method:    grayPhoto
 * Signature: (Landroid/graphics/Bitmap;Landroid/graphics/Bitmap;)V
 */
/**
 * xuan
 */
#define  LOG_TAG    "PhotoProcessing"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

typedef struct {
	uint8_t alpha;
	uint8_t red;
	uint8_t green;
	uint8_t blue;
} argb;

JNIEXPORT void JNICALL Java_com_example_photoprocessing_activity_PhotoProcessingActivity_grayPhoto
  (JNIEnv *, jobject, jobject, jobject);

#ifdef __cplusplus
}
#endif
#endif

接着编写C代码

#include "PhotoProcessingActivity.h"

JNIEXPORT void JNICALL Java_com_example_photoprocessing_activity_PhotoProcessingActivity_grayPhoto(
		JNIEnv *env, jobject photoProcessingActivity, jobject bmOriginal,
		jobject bmGray) {
	AndroidBitmapInfo origanalColor;
	void* pixelscolor;
	AndroidBitmapInfo infogray;
	void* pixelsgray;
	int ret;
	int y;
	int x;

	LOGI("In convertToGray");
	if ((ret = AndroidBitmap_getInfo(env, bmOriginal, &origanalColor)) < 0) {
		LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
		return;
	}

	if ((ret = AndroidBitmap_getInfo(env, bmGray, &infogray)) < 0) {
		LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
		return;
	}
	LOGI(
			"original image :: width is %d; height is %d; stride is %d; format is %d;flags is	%d,stride is %u", origanalColor.width, origanalColor.height, origanalColor.stride, origanalColor.format, origanalColor.flags, origanalColor.stride);

	if (origanalColor.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
		LOGE("Bitmap format is not RGBA_8888 !");
		//return;
	}

	if (origanalColor.format == ANDROID_BITMAP_FORMAT_RGB_565) {
		LOGI("Original Image is ANDROID_BITMAP_FORMAT_RGB_565");

		if ((ret = AndroidBitmap_lockPixels(env, bmOriginal, &pixelscolor))
				< 0) {
			LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
		}

		if ((ret = AndroidBitmap_lockPixels(env, bmGray, &pixelsgray)) < 0) {
			LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
		}
		// modify pixels with image processing algorithm
		for (y = 0; y < origanalColor.height; y++) {
			__uint16_t * line = (__uint16_t *) pixelscolor;
			uint8_t * grayline = (uint8_t *) pixelsgray;
			for (x = 0; x < origanalColor.width; x++) {
				grayline[x] = (uint8_t)(((line[x] >> 11 <<3) + (line[x] >> 5 & 63 * 16) + (line[x]&31 * 8)) / 3);
				//LOGI("%d %d %d %d",line[x].alpha,line[x].red,line[x].green,line[x].blue);
				/*if(x ==0){
				LOGI("line:%o  grayline %o ",line[x],grayline[x]);
				}*/
			}
			pixelscolor = (char *) pixelscolor + origanalColor.stride;
			pixelsgray = (char *) pixelsgray + infogray.stride;
		}

		LOGI("unlocking pixels");
		AndroidBitmap_unlockPixels(env, bmOriginal);
		AndroidBitmap_unlockPixels(env, bmGray);
		LOGI("Return !! ");
		return ;
	}

	LOGI(
			"gray image :: width is %d; height is %d; stride is %d; format is %d;flags is %d %d,stride is %u", infogray.width, infogray.height, infogray.stride, infogray.format, infogray.flags, infogray.stride);
	if (infogray.format != ANDROID_BITMAP_FORMAT_A_8) {
		LOGE("Bitmap format is not A_8 !");
		return;
	}

	if ((ret = AndroidBitmap_lockPixels(env, bmOriginal, &pixelscolor)) < 0) {
		LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
	}

	if ((ret = AndroidBitmap_lockPixels(env, bmGray, &pixelsgray)) < 0) {
		LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
	}

	// modify pixels with image processing algorithm
	for (y = 0; y < origanalColor.height; y++) {
		argb * line = (argb *) pixelscolor;
		uint8_t * grayline = (uint8_t *) pixelsgray;
		for (x = 0; x < origanalColor.width; x++) {
			grayline[x] = (line[x].red + line[x].green + line[x].blue) / 3;
		}
		pixelscolor = (char *) pixelscolor + origanalColor.stride;
		pixelsgray = (char *) pixelsgray + infogray.stride;
	}

	LOGI("unlocking pixels");
	AndroidBitmap_unlockPixels(env, bmOriginal);
	AndroidBitmap_unlockPixels(env, bmGray);
}

编写Android.mk文件,该文件主要是指明要使用的.so文件,并且生成我们自己的.so文件

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := PhotoProcessing
LOCAL_SRC_FILES := PhotoProcessing.cpp
LOCAL_LDLIBS    := -llog -ljnigraphics

include $(BUILD_SHARED_LIBRARY)

关键的一些代码就是这些了,其中处理的灰度算法可能不是非常优化,这其中处理RGB565部分是我自己根据图像处理中灰度的定义所写的,其中也要感谢孙志海大哥对我的帮助 !!

可以说使用这种方法还是比较简易的,但是,似乎仍没解决我一开头说道的问题,即这种方式仅仅是提升了程序的效率,但依然需要在UI线程中更新界面,这里也可以使用SurfaceVIew来进行异步的更新界面,但是这里,我想知道,在不修改android系统源码情况下,NDK的极限,即它能否直接控制View的surface,使其不通过java代码就直接把界面刷新呢?这个可能会涉及到Linux的文件权限问题,以及需要翻阅android系统源码。

望对这个方面感兴趣的朋友,能够和我一起交流,或者能够给我一些建议。我的QQ是835060947,也可以发邮件给我。

时间: 2024-10-10 06:48:58

Android 使用NDK处理BItmap及如何通过C/C++直接控制View的suface显示,学习笔记及方向的相关文章

在Ubuntu上为Android系统内置Java应用程序测试Application Frameworks层的硬件服务(老罗学习笔记)

一:Eclipse下 1.创建工程: ---- 2.创建后目录 3.添加java函数 4.在src下创建package,在package下创建file 5.res---layout下创建xml文件,命名main 6.project下清楚错误 7.位解决错误 ① ② 8.总体目录 9.当删除工程后,可以import再重新导入工程. 二:源码下 ① 将Hello目录拷贝至packages/experimental目录,新增Android.mk文件:    [email protected]:~/An

Delphi使用android的NDK是通过JNI接口,封装好了,不用自己写本地代码,直接调用

一.Android平台编程方式:      1.基于Android SDK进行开发的第三方应用都必须使用Java语言(Android的SDK基于Java实现)      2.自从ndk r5发布以后,已经允许完全用C/C++ 来开发应用或者游戏,而不再需要编写任何Java 的代码   Android程序运行在Dalvik虚拟机中,NDK允许用户使用类似C / C++之类的原生代码语言执行部分程序. 二.跨平台移动开发   Delphi使用android的NDK是通过JNI接口,封装好了,不用自己

Android NDK学习笔记(一) 为什么要用NDK?

NDK是什么 NDK是Native Development Kit的简称,即本地开发工具包.通过NDK,Android允许开发人员使用本地代码语言(例如C/C++)来完成应用的部分(甚至全部)功能.注意:由于翻译原因,有些地方也把Native翻译为"原生". NDK是SDK的一个补充,可以帮助你做这些事情: 生成可以在ARM CPU,Android 1.5(及以上)平台运行的JNI兼容的共享库. 将生成的共享库放置在应用程序项目路径的合适位置,使其能自动地添加进你最终的(和经过签名的)

android studio NDK 开发初探

android studio NDK 开发初探 环境配置 1)下载ndk 2)在android studio中配置ndk 路径 3)配置gradle 在gradle.properties中加入 android.useDeprecatedNdk=true配置 开启ndk 在开发过程中我们有时还会用到c++中到stl库这时我们就需要在build.gradle 中加入 defaultConfig { ndk { moduleName "jnitest" stl "stlport_s

【转】 Android的NDK开发(1)————Android JNI简介与调用流程

原文网址:http://blog.csdn.net/conowen/article/details/7521340 ******************************************************************************************** * author:[email protected]大钟                                                                      

android eclipse NDK 测试hello-jni ,HelloJni/jni/hello-jni.c提示“Method &#39;NewStringUTF&#39; could not be resolved”

如图1 图1 问题: 方法 NewStringUTF 不能被 eclipse定位(鼠标放在该方法上,ctrl + 左键,跳出一些包含 该方法的文件,看图2) 解决思路:(具体思路看下文,参考中“推荐”) 参考网上其他人的解决方案,基本2类: 1. 去警告-> 看下图3: 2. 找到错误方法所在文件位置(图3),包含进 项目属性(propertities -> C/C++ General -> Paths and Sysmbols -> include -> add ->

ubuntu12.04 安装android sdk /ndk/源码 编译环境

做android已经近5年了,期间android的各种环境都自己配过,自己是个想法比较多的人,各自神奇到想法都有,包括写博客,但是一直是没有具体落实...想法再多,不去努力实现也只能是想法了,今天准备从写博客这个小事开始做起,磨练自己到,不废话了,直接进入主题: 一.JDK(下载并安装jdk),注意事项如下: a.32位需要下32的,64位的也注意是下载64位的: b.配置环境变量: $ sudo gedit /etc/profile           在文件的末尾加上如下内容:       

android的NDK和java进行本地socket通信

关于Android应用与Framework的socket通信,相信关心这个问题的朋友们已经看过<android使用socket使底层和framework通信>这篇文章,美中不足的是作者只贴出一些关键的代码片段而并没有放出源码.我这里还是以一个能实际运行的例子为基础来讲,这样也方便大家学习. 首先看一下效果,如下图.我填写姓名"Potter",选择性别"Mr"然后点击发送,底层socket收到消息后将消息直接返回给我,我将返回的结果(Mr.Potter)直

Android Studio NDK开发

整理完Eclipse的NDK开发,再整理下Android Studio的.. 一个比较不错的百度网盘: http://pan.baidu.com/share/home?uk=2383159761  经常更新最新的Android方面的开发包,可以到里面下载到ndk的包 创建一个Android的工程,放一个TextView用于显示文字,功能很简单,从native层获取字符串并显示到TextView上 然后编写相关代码: public class MainActivity extends AppCom