Android提高十六篇之使用NDK把彩图转换灰度图

本文来自http://blog.csdn.net/hellogv/,引用必须注明出处!

在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文件。

接下来看看本文程序运行的效果:

Android提高十六篇之使用NDK把彩图转换灰度图

从转换灰度图的耗时来说,NDK的确比JAVA所用的时间短不少。

main.xml源码如下:

  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. -<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="fill_parent"android:layout_height="fill_parent">
  3. <Buttonandroid:layout_height="wrap_content"android:layout_width="fill_parent"android:id="@+id/btnJAVA"android:text="使用JAVA转换灰度图"/>
  4. <Buttonandroid:layout_height="wrap_content"android:layout_width="fill_parent"android:id="@+id/btnNDK"android:text="使用NDK转换灰度图"/>
  5. <ImageViewandroid:id="@+id/ImageView01"android:layout_width="fill_parent"android:layout_height="fill_parent"/>
  6. </LinearLayout>

主程序testToGray.java的源码如下:

  1. packagecom.testToGray;
  2. importandroid.app.Activity;
  3. importandroid.graphics.Bitmap;
  4. importandroid.graphics.Bitmap.Config;
  5. importandroid.graphics.drawable.BitmapDrawable;
  6. importandroid.os.Bundle;
  7. importandroid.view.View;
  8. importandroid.widget.Button;
  9. importandroid.widget.ImageView;
  10. publicclasstestToGrayextendsActivity{
  11. /**Calledwhentheactivityisfirstcreated.*/
  12. ButtonbtnJAVA,btnNDK;
  13. ImageViewimgView;
  14. @Override
  15. publicvoidonCreate(BundlesavedInstanceState){
  16. super.onCreate(savedInstanceState);
  17. setContentView(R.layout.main);
  18. this.setTitle("使用NDK转换灰度图---hellogv");
  19. btnJAVA=(Button)this.findViewById(R.id.btnJAVA);
  20. btnJAVA.setOnClickListener(newClickEvent());
  21. btnNDK=(Button)this.findViewById(R.id.btnNDK);
  22. btnNDK.setOnClickListener(newClickEvent());
  23. imgView=(ImageView)this.findViewById(R.id.ImageView01);
  24. }
  25. classClickEventimplementsView.OnClickListener{
  26. @Override
  27. publicvoidonClick(Viewv){
  28. if(v==btnJAVA)
  29. {
  30. longcurrent=System.currentTimeMillis();
  31. Bitmapimg=ConvertGrayImg(R.drawable.cat);
  32. longperformance=System.currentTimeMillis()-current;
  33. //显示灰度图
  34. imgView.setImageBitmap(img);
  35. testToGray.this.setTitle("w:"+String.valueOf(img.getWidth())+",h:"+String.valueOf(img.getHeight())
  36. +"JAVA耗时"+String.valueOf(performance)+"毫秒");
  37. }
  38. elseif(v==btnNDK)
  39. {
  40. longcurrent=System.currentTimeMillis();
  41. //先打开图像并读取像素
  42. Bitmapimg1=((BitmapDrawable)getResources().getDrawable(R.drawable.cat)).getBitmap();
  43. intw=img1.getWidth(),h=img1.getHeight();
  44. int[]pix=newint[w*h];
  45. img1.getPixels(pix,0,w,0,0,w,h);
  46. //通过ImgToGray.so把彩色像素转为灰度像素
  47. int[]resultInt=LibFuns.ImgToGray(pix,w,h);
  48. BitmapresultImg=Bitmap.createBitmap(w,h,Config.RGB_565);
  49. resultImg.setPixels(resultInt,0,w,0,0,w,h);
  50. longperformance=System.currentTimeMillis()-current;
  51. //显示灰度图
  52. imgView.setImageBitmap(resultImg);
  53. testToGray.this.setTitle("w:"+String.valueOf(img1.getWidth())+",h:"+String.valueOf(img1.getHeight())
  54. +"NDK耗时"+String.valueOf(performance)+"毫秒");
  55. }
  56. }
  57. }
  58. /**
  59. *把资源图片转为灰度图
  60. *@paramresID资源ID
  61. *@return
  62. */
  63. publicBitmapConvertGrayImg(intresID)
  64. {
  65. Bitmapimg1=((BitmapDrawable)getResources().getDrawable(resID)).getBitmap();
  66. intw=img1.getWidth(),h=img1.getHeight();
  67. int[]pix=newint[w*h];
  68. img1.getPixels(pix,0,w,0,0,w,h);
  69. intalpha=0xFF<<24;
  70. for(inti=0;i<h;i++){
  71. for(intj=0;j<w;j++){
  72. //获得像素的颜色
  73. intcolor=pix[w*i+j];
  74. intred=((color&0x00FF0000)>>16);
  75. intgreen=((color&0x0000FF00)>>8);
  76. intblue=color&0x000000FF;
  77. color=(red+green+blue)/3;
  78. color=alpha|(color<<16)|(color<<8)|color;
  79. pix[w*i+j]=color;
  80. }
  81. }
  82. Bitmapresult=Bitmap.createBitmap(w,h,Config.RGB_565);
  83. result.setPixels(pix,0,w,0,0,w,h);
  84. returnresult;
  85. }
  86. }

封装NDK函数的JAVA类LibFuns.java的源码如下:

  1. packagecom.testToGray;
  2. publicclassLibFuns{
  3. static{
  4. System.loadLibrary("ImgToGray");
  5. }
  6. /**
  7. *@paramwidththecurrentviewwidth
  8. *@paramheightthecurrentviewheight
  9. */
  10. publicstaticnativeint[]ImgToGray(int[]buf,intw,inth);
  11. }

彩图转换为灰度图的ImgToGray.cpp源码:

  1. #include<jni.h>
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. extern"C"{
  5. JNIEXPORTjintArrayJNICALLJava_com_testToGray_LibFuns_ImgToGray(
  6. JNIEnv*env,jobjectobj,jintArraybuf,intw,inth);
  7. }
  8. ;
  9. JNIEXPORTjintArrayJNICALLJava_com_testToGray_LibFuns_ImgToGray(
  10. JNIEnv*env,jobjectobj,jintArraybuf,intw,inth){
  11. jint*cbuf;
  12. cbuf=env->GetIntArrayElements(buf,false);
  13. if(cbuf==NULL){
  14. return0;/*exceptionoccurred*/
  15. }
  16. intalpha=0xFF<<24;
  17. for(inti=0;i<h;i++){
  18. for(intj=0;j<w;j++){
  19. //获得像素的颜色
  20. intcolor=cbuf[w*i+j];
  21. intred=((color&0x00FF0000)>>16);
  22. intgreen=((color&0x0000FF00)>>8);
  23. intblue=color&0x000000FF;
  24. color=(red+green+blue)/3;
  25. color=alpha|(color<<16)|(color<<8)|color;
  26. cbuf[w*i+j]=color;
  27. }
  28. }
  29. intsize=w*h;
  30. jintArrayresult=env->NewIntArray(size);
  31. env->SetIntArrayRegion(result,0,size,cbuf);
  32. env->ReleaseIntArrayElements(buf,cbuf,0);
  33. returnresult;
  34. }

Android.mk的源码:

  1. LOCAL_PATH:=$(callmy-dir)
  2. include$(CLEAR_VARS)
  3. LOCAL_MODULE:=ImgToGray
  4. LOCAL_SRC_FILES:=ImgToGray.cpp
  5. include$(BUILD_SHARED_LIBRARY)


你可能感兴趣的:(android)