一般而言在android上使用java实现彩图转换为灰度图,与j2me上的实现方法类似,不过遇到频繁地转换或者是大图转换时,就必须使用ndk来提高速度了。本文主要通过java和ndk这两种方式来分别实现彩图转换为灰度图,并给出速度的对比,供大家参考。
先来简单地介绍一下android的ndk使用步骤:
以ndk r4为例,或许以后新版的ndk的使用方法略有不同。
1、下载支持c++的android-ndk-r4-crystax,支持c++的话可玩性更强。
2、下载cygwin,选择ftp://mirrors.kernel.org这个镜像,搜索 devel install 安装 gcc 和 make 等工具;
如图所示:
在搜索框里分别搜索gcc和make,必须是 devel install 栏的。
3、cygwin安装目录下,找到home/username的目录下的.bash_profile文件,打开文件在最后加上:
ndk=/cygdrive/d:cygwin/android-ndk-r4-crystax
export ndk
ps:假设安装在d:/cygwin/android-ndk-r4-crystax。
4、运行cygwin,通过cd命令去到ndk/samples/例子目录/,运行$ndk/ndk-build来编译该目录下的android.mk
以下是个人习惯
5、安装eclipse的cdt,官方下载cdt安装包,解压缩后把plugins和feagures 复制覆盖到eclipse文件夹下即可
6、去到系统属性->环境变量->path添加"d:/cygwin/bin"(假设cygwin安装在d:下)和"d:/cygwin/android-ndk-r4-crystax",重启计算机,然后就可以在eclipse里面建立基于cygwin的c/c++工程了,先通过这一步来验证ndk的程序能够编译成功,然后再通过第4步来生成so文件。
接下来看看本文程序运行的效果:
从转换灰度图的耗时来说,ndk的确比java所用的时间短不少。
main.xml源码如下:
1
2
3
4
5
6
|
<?xml version= "1.0" encoding= "utf-8" ?> - <linearlayout xmlns:android= "http://schemas.android.com/apk/res/android" android:orientation= "vertical" android:layout_width= "fill_parent" android:layout_height= "fill_parent" > <button android:layout_height= "wrap_content" android:layout_width= "fill_parent" android:id= "@+id/btnjava" android:text= "使用java转换灰度图" /> <button android:layout_height= "wrap_content" android:layout_width= "fill_parent" android:id= "@+id/btnndk" android:text= "使用ndk转换灰度图" /> <imageview android:id= "@+id/imageview01" android:layout_width= "fill_parent" android:layout_height= "fill_parent" /> </linearlayout> |
主程序testtogray.java的源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
package com.testtogray; import android.app.activity; import android.graphics.bitmap; import android.graphics.bitmap.config; import android.graphics.drawable.bitmapdrawable; import android.os.bundle; import android.view.view; import android.widget.button; import android.widget.imageview; public class testtogray extends activity { /** called when the activity is first created. */ button btnjava,btnndk; imageview imgview; @override public void oncreate(bundle savedinstancestate) { super .oncreate(savedinstancestate); setcontentview(r.layout.main); this .settitle( "使用ndk转换灰度图---hellogv" ); btnjava=(button) this .findviewbyid(r.id.btnjava); btnjava.setonclicklistener( new clickevent()); btnndk=(button) this .findviewbyid(r.id.btnndk); btnndk.setonclicklistener( new clickevent()); imgview=(imageview) this .findviewbyid(r.id.imageview01); } class clickevent implements view.onclicklistener{ @override public void onclick(view v) { if (v==btnjava) { long current=system.currenttimemillis(); bitmap img=convertgrayimg(r.drawable.cat); long performance=system.currenttimemillis()-current; //显示灰度图 imgview.setimagebitmap(img); testtogray. this .settitle( "w:" +string.valueof(img.getwidth())+ ",h:" +string.valueof(img.getheight()) + " java耗时 " +string.valueof(performance)+ " 毫秒" ); } else if (v==btnndk) { long current=system.currenttimemillis(); //先打开图像并读取像素 bitmap img1=((bitmapdrawable) getresources().getdrawable(r.drawable.cat)).getbitmap(); int w=img1.getwidth(),h=img1.getheight(); int [] pix = new int [w * h]; img1.getpixels(pix, 0 , w, 0 , 0 , w, h); //通过imgtogray.so把彩色像素转为灰度像素 int [] resultint=libfuns.imgtogray(pix, w, h); bitmap resultimg=bitmap.createbitmap(w, h, config.rgb_565); resultimg.setpixels(resultint, 0 , w, 0 , 0 ,w, h); long performance=system.currenttimemillis()-current; //显示灰度图 imgview.setimagebitmap(resultimg); testtogray. this .settitle( "w:" +string.valueof(img1.getwidth())+ ",h:" +string.valueof(img1.getheight()) + " ndk耗时 " +string.valueof(performance)+ " 毫秒" ); } } } /** * 把资源图片转为灰度图 * @param resid 资源id * @return */ public bitmap convertgrayimg( int resid) { bitmap img1=((bitmapdrawable) getresources().getdrawable(resid)).getbitmap(); int w=img1.getwidth(),h=img1.getheight(); int [] pix = new int [w * h]; img1.getpixels(pix, 0 , w, 0 , 0 , w, h); int alpha= 0xff << 24 ; for ( int i = 0 ; i < h; i++) { for ( int j = 0 ; j < w; j++) { // 获得像素的颜色 int color = pix[w * i + j]; int red = ((color & 0x00ff0000 ) >> 16 ); int green = ((color & 0x0000ff00 ) >> 8 ); int blue = color & 0x000000ff ; color = (red + green + blue)/ 3 ; color = alpha | (color << 16 ) | (color << 8 ) | color; pix[w * i + j] = color; } } bitmap result=bitmap.createbitmap(w, h, config.rgb_565); result.setpixels(pix, 0 , w, 0 , 0 ,w, h); return result; } } |
封装ndk函数的java类libfuns.java的源码如下:
1
2
3
4
5
6
7
8
9
10
11
|
package com.testtogray; public class libfuns { static { system.loadlibrary( "imgtogray" ); } /** * @param width the current view width * @param height the current view height */ public static native int [] imgtogray( int [] buf, int w, int h); } |
彩图转换为灰度图的imgtogray.cpp源码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
#include <jni.h> #include <stdio.h> #include <stdlib.h> extern "c" { jniexport jintarray jnicall java_com_testtogray_libfuns_imgtogray( jnienv* env, jobject obj, jintarray buf, int w, int h); } ; jniexport jintarray jnicall java_com_testtogray_libfuns_imgtogray( jnienv* env, jobject obj, jintarray buf, int w, int h) { jint *cbuf; cbuf = env->getintarrayelements(buf, false ); if (cbuf == null ) { return 0 ; /* exception occurred */ } int alpha = 0xff << 24 ; for ( int i = 0 ; i < h; i++) { for ( int j = 0 ; j < w; j++) { // 获得像素的颜色 int color = cbuf[w * i + j]; int red = ((color & 0x00ff0000 ) >> 16 ); int green = ((color & 0x0000ff00 ) >> 8 ); int blue = color & 0x000000ff ; color = (red + green + blue) / 3 ; color = alpha | (color << 16 ) | (color << 8 ) | color; cbuf[w * i + j] = color; } } int size=w * h; jintarray result = env->newintarray(size); env->setintarrayregion(result, 0 , size, cbuf); env->releaseintarrayelements(buf, cbuf, 0 ); return result; } |
android.mk的源码:
1
2
3
4
5
|
local_path:= $(call my-dir) include $(clear_vars) local_module := imgtogray local_src_files := imgtogray.cpp include $(build_shared_library) |
感兴趣的读者可以动手调试一下本文所述代码,相信会对大家进行android项目开发有一定的帮助。