在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/android-ndk-r4-windows/android-ndk-r4
export NDK
PS:假设安装在d:\android-ndk-r4-windows\android-ndk-r4。
4、运行cygwin,通过cd命令去到NDK\samples\例子目录\,运行$NDK/ndk-build来编译该目录下的Android.mk
以下是个人习惯.......
5、安装Eclipse的CDT,官方下载cdt安装包,解压缩后把plugins和feagures 复制覆盖到eclipse文件夹下即可
6、
去到系统属性->环境变量->Path添加"D:\cygwin\bin"(假设cygwin安装在D:下),重启计算机,然后就可以在
Eclipse里面建立基于cygwin的C/C++工程了,先通过这一步来验证NDK的程序能够编译成功,然后再通过第4步来生成SO文件。
接下来看看本文程序运行的效果:
从转换灰度图的耗时来说,NDK的确比JAVA所用的时间短不少。
main.xml源码如下:
-
<?
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的源码如下:
-
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 {
-
-
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);
-
-
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)+
" 毫秒"
);
-
}
-
}
-
}
-
-
-
-
-
-
-
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的源码如下:
-
package
com.testToGray;
-
public
class
LibFuns {
-
static
{
-
System.loadLibrary("ImgToGray"
);
-
}
-
-
-
-
-
-
-
public
static
native
int
[] ImgToGray(
int
[] buf,
int
w,
int
h);
-
}
彩图转换为灰度图的ImgToGray.cpp源码:
-
#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;
-
}
-
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的源码:
-
LOCAL_PATH:
= $(call my-dir)
-
-
include $(CLEAR_VARS)
-
-
LOCAL_MODULE :
=
ImgToGray
-
LOCAL_SRC_FILES :
=
ImgToGray
.cpp
-
-
include $(BUILD_SHARED_LIBRARY)
分享到:
相关推荐
总结来说,使用Android NDK处理图像转换,特别是彩图转灰度图,是一种有效的优化策略。通过编写原生代码,我们可以利用C或C++的强大功能,以更高的效率完成计算密集型任务,为Android应用带来更好的性能表现。
《Android C++高级编程——使用NDK》提供了Java原生接口(JNI)的概述、Bionic API、POSIX 线程和套接字、C++支持、原生图形和声音API以及NEON/SIMD优化,在一个游戏应用案例的帮助下,你将学到很多关键技能。...
Android NDK(Native Development Kit)提供了一种方法来实现这样的编码转换,这就是使用Iconv库。Iconv是一个广泛使用的字符集转换工具,它允许在多种字符编码之间进行转换,包括Unicode、GBK和UTF-8。 Iconv在C/...
Android允许应用开发者通过Android原生开发包(NDK)使用诸如C和C++之类的原生代码语言实现他们的部分应用。《移动开发经典丛书·Android C++高级编程:使用NDK》中我们将学习如何用AndroidNDK通过原生代码语言去...
《Android C++高级编程:使用NDK》是一本深度探讨Android平台上C++开发技术的权威著作,完整版带有书签,方便读者随时查阅和学习。本书主要针对Android开发者,特别是那些希望利用C++来提升应用性能、降低内存占用...
Android C++高级编程:使用NDK
在Android应用开发中,NDK扮演着至关重要的角色,它允许开发者使用原生代码(如C和C++)来编写部分应用,以提高性能、利用硬件加速功能或复用现有的C/C++库。 1. **JNI(Java Native Interface)**: JNI是Java...
NDK是Android应用开发中的一个重要组成部分,它允许开发者使用原生代码(如C、C++)来编写部分应用程序,从而利用底层的硬件性能,提高程序运行效率,尤其是在处理图形计算、物理模拟和游戏引擎等高性能需求的场景下...
《Android C++高级编程:使用NDK》是一本专注于探讨如何在Android平台上进行C++开发的专业书籍。Android NDK(Native Development Kit)是Google提供的一个工具集,它允许开发者使用原生代码(如C和C++)来编写部分...
《Android C++高级编程:使用NDK》是一本专为Android开发者深入理解并掌握NDK技术而编写的书籍。NDK(Native Development Kit)是Google提供的一种工具集,允许开发者在Android平台上使用C和C++编写原生代码,从而...
Android NDK,全称为Native Development Kit,是Google提供的一款用于Android平台的C和C++库开发工具集。这个工具允许开发者在Android应用中使用原生代码,以实现高性能计算、图形处理、游戏引擎等复杂功能。`...
Android NDK,全称为Native Development Kit,是Google提供的一款用于Android平台的C和C++库开发工具集。这个“android-ndk-r23b-linux.zip”文件是NDK的一个特定版本,即r23b,专为Linux操作系统设计。在Android...
Android NDK,全称为Native Development Kit,是Google提供的一款用于Android平台的C和C++开发工具集。这个压缩包“android-ndk-r26b-windows.zip”包含了NDK的第26个版本,专为Windows操作系统设计。通过这个工具,...
Android NDK(Native Development Kit)是Google提供的一款工具,允许开发者在Android应用中使用原生代码(如C/C++),以提升性能,尤其是处理计算密集型任务,如图像处理。本项目"android-image-filter-ndk"是一个...
Android NDK,全称为Native Development Kit,是Google提供的一款用于Android平台的C和C++开发工具集。这个压缩包“android-ndk-r25b-windows.zip”包含了NDK的第25个版本,专为Windows操作系统设计。NDK的主要功能...
ndk-Android C++高级编程:使用NDK_Onur Cinar,于红.zipndk-Android C++高级编程:使用NDK_Onur Cinar,于红.zipndk-Android C++高级编程:使用NDK_Onur Cinar,于红.zipndk-Android C++高级编程:使用NDK_Onur Cinar,...
《Android C++高级编程使用NDK》是一本深入探讨如何在Android平台上利用C++进行高效开发的专业书籍。这本书源码的提供,对于开发者来说是一份宝贵的参考资料,它涵盖了多个章节的示例代码,帮助读者更好地理解和实践...
Android NDK,全称为Native Development Kit,是Google提供的一款用于Android平台的开发工具,它允许开发者使用C++和其他原生编程语言编写应用的部分或全部代码。这个“android-ndk-r26b-linux.zip”文件是NDK的一个...