程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> Android 使用NDK處理BItmap及如何通過C/C++直接控制View的suface顯示,學習筆記及方向

Android 使用NDK處理BItmap及如何通過C/C++直接控制View的suface顯示,學習筆記及方向

編輯:C++入門知識

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 
/* Header for class com_example_photoprocessing_activity_PhotoProcessingActivity */
#include 
#include 
#include 
#include 


#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,也可以發郵件給我。




  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved