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

2015-01-27 06:14:51 · 作者: · 浏览: 39
_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代码就直接把界