Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android NDK使用libjpeg解析JPEG圖片,並顯示到SurfaceView上

Android NDK使用libjpeg解析JPEG圖片,並顯示到SurfaceView上

編輯:關於Android編程

SurfaceView大概是谷歌提供給開發者最吸引人的的組件了,原因是SurfaceView的界面刷新允許在非UI線程中更新,正因為此,很多頻繁更新界面的應用,如視頻播放器、游戲、動畫效果總會基於SurfaceView及其子類進行開發。

而最近我正在研究的一個應用是關於處理圖片並顯示圖片的應用,圖片實在是內存殺手,而處理圖片則運算量非常大,這些都是令人頭疼的問題。

分析應用,並選擇實現技術

1、處理圖片運算量大,為了提高運算效率,選擇使用C語言處理圖片

2、需要的內存空間較大,為節約內存並提高效率,需要從C語言中讀入文件,並及早釋放


下面寫下展示圖片的基本流程

1、用戶選擇圖片

2、獲得用戶選擇的圖片的路徑

3、調用展示圖片的方法(C方法)


第一部分:用戶選擇圖片

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);// ACTION_OPEN_DOCUMENT
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/jpeg");
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
	startActivityForResult(intent, SELECT_PIC_KITKAT);
} else {
	startActivityForResult(intent, SELECT_PIC);
}


第二部分獲得用戶選擇的圖片的路徑

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (resultCode == RESULT_OK) {

			if (requestCode == SELECT_PIC) {
				Uri originalUri = data.getData();
				String[] proj = { MediaStore.Images.Media.DATA };
				// 好像是android多媒體數據庫的封裝接口,具體的看Android文檔
				Cursor cursor = managedQuery(originalUri, proj, null, null,
						null);
				// 按我個人理解 這個是獲得用戶選擇的圖片的索引值
				int column_index = cursor
						.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
				// 將光標移至開頭 ,這個很重要,不小心很容易引起越界
				cursor.moveToFirst();
				// 最後根據索引值獲取圖片路徑
				String path = cursor.getString(column_index);
				Log.v("圖片路徑: ", path);

				if (path.endsWith(".jpg")) {
					isOnActivityResult = true;
					imgPath = path;
				}
			}
		}
	};

第三部分:調用展示圖片的方法

這個部分需要注意,寫在SurfaceHolder的回調方法內,為的是讓SurfaceView中的Surface成功建立後,再將Surface傳入C代碼中進行處理

		svShow = (SurfaceView) findViewById(R.id.svShow);
		svHolder = svShow.getHolder();

		svHolder.addCallback(new SurfaceHolder.Callback() {

			public void surfaceChanged(SurfaceHolder holder, int format,
					int width, int height) {
				Log.v(TAG, "surfaceChanged format=" + format + ", width="
						+ width + ", height=" + height);
			}

			public void surfaceCreated(SurfaceHolder holder) {
				Log.v(TAG, "surfaceCreated");
				if (isOnActivityResult && imgPath != null) {
					showJPG(holder.getSurface(), imgPath);
				}
			}

			public void surfaceDestroyed(SurfaceHolder holder) {
				Log.v(TAG, "surfaceDestroyed");
			}

		});


實際處理圖片並顯示圖片的代碼

JNIEXPORT void JNICALL Java_com_example_photoprocessing_activity_SurfaceProcessingActivity_showJPG(
		JNIEnv * env, jobject activity, jobject surface, jstring img) {
	const char * imgChar;
	jboolean * isCopy;
	imgChar = env->GetStringUTFChars(img, 0);
	ANativeWindow_Buffer nwBuffer;

	LOGI("img path : %s  ",imgChar);

	LOGI("ANativeWindow_fromSurface ");
	ANativeWindow * mANativeWindow = ANativeWindow_fromSurface(env, surface);

	if (mANativeWindow == NULL) {
		LOGE("ANativeWindow_fromSurface error");
		return;
	}

	LOGI("ANativeWindow_lock ");
	if (0 != ANativeWindow_lock(mANativeWindow, &nwBuffer, 0)) {
		LOGE("ANativeWindow_lock error");
		return;
	}

	read_jpeg_file_show(imgChar, nwBuffer);

	if (nwBuffer.format == WINDOW_FORMAT_RGBA_8888) {
		LOGI("nwBuffer->format == WINDOW_FORMAT_RGBA_8888 ");
	}

	LOGI("ANativeWindow_unlockAndPost ");
	if (0 != ANativeWindow_unlockAndPost(mANativeWindow)) {
		LOGE("ANativeWindow_unlockAndPost error");
		return;
	}

	env->ReleaseStringUTFChars(img,imgChar);
	ANativeWindow_release(mANativeWindow);
	LOGI("ANativeWindow_release ");
	return;
}
int read_jpeg_file_show(const char *input_filename,
		ANativeWindow_Buffer& nwBuffer) {
	struct jpeg_decompress_struct cinfo;
	struct jpeg_error_mgr jerr;
	FILE *input_file;
	JSAMPARRAY buffer;
	int row_width;

	unsigned char *buffertmp;

	cinfo.err = jpeg_std_error(&jerr);

	if ((input_file = fopen(input_filename, "rb")) == NULL) {
		fprintf(stderr, "can't open %s\n", input_filename);
		LOGI("can't open jpg1");
		return -1;
	}

	//初始化信息
	jpeg_create_decompress(&cinfo);
	LOGI("初始化信息");

	/* Specify data source for decompression */
	//指定圖片
	jpeg_stdio_src(&cinfo, input_file);
	LOGI("指定圖片");

	/* Read file header, set default decompression parameters */
	(void) jpeg_read_header(&cinfo, TRUE);
	LOGI("讀取頭信息, set default decompression parameters ");

	/* Start decompressor */
	(void) jpeg_start_decompress(&cinfo);
	LOGI("解壓");

	row_width = cinfo.output_width * cinfo.output_components;
	LOGI(
			"圖片的寬:%d 圖片的高%d 顏色長度:%d", cinfo.output_width, cinfo.output_height, cinfo.output_components);

	buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE,
			row_width, 1);

	//一行
	buffertmp = (unsigned char *) malloc(row_width);
	memset(buffertmp, 0, row_width);
	LOGI("malloc and memset");
//        tmp = output_buffer;

	/* Process data */
	int get8h5 = 248, get8h6 = 252;
	__uint16_t * line = (__uint16_t *) nwBuffer.bits;
	int wheight = 0;

	int scalew = 1, scaleh = 1;

	if (cinfo.output_width > nwBuffer.width) {
		scalew = cinfo.output_width / nwBuffer.width;
	}

	LOGI(" scale of img = %d", scalew);

	for (int i = 0, choosehNum = 0; i < cinfo.output_height; i++) {
		//獲得一行
		jpeg_read_scanlines(&cinfo, buffer, 1);
		buffertmp = *buffer;
		//根據縮放選取行
		if (i % scalew == 0 && choosehNum++ < nwBuffer.height) {

			//LOGI("nwBuffer->format == WINDOW_FORMAT_RGB_565");
			for (int j = 0, choosewNum = 0; j < cinfo.output_width; j++) {
				if (j % scalew == 0) {
					if (nwBuffer.format == WINDOW_FORMAT_RGB_565) {
						line[choosewNum] = ((__uint16_t ) buffertmp[3 * j + 0]
								& get8h5) << 8
								| ((__uint16_t ) (buffertmp[3 * j + 1] & get8h6)
										<< 3)
								| ((__uint16_t ) (buffertmp[3 * j + 2] & get8h6)
										>> 3);
						choosewNum++;
					}
				}

			}
			line = line + nwBuffer.stride;
		}
	}

//                memcpy(tmp, *buffer, row_width);
//                tmp += row_width;

	(void) jpeg_finish_decompress(&cinfo);
	LOGI("jpeg_finish_decompress !!");

	jpeg_destroy_decompress(&cinfo);
	LOGI("jpeg_destroy_decompress !!");

	/* Close files, if we opened them */
	fclose(input_file);

	return 0;
}

Demo展示:

點擊顯示圖片,開始選擇圖片:

\

選擇完後,自動顯示:<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+PGltZyBzcmM9"/uploadfile/Collfiles/20141208/20141208084605119.png" alt="">




  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved