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

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

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

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

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

main.xml源码如下:

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

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

  1. package  com.testToGray;  
  2.   
  3. import  android.app.Activity;  
  4. import  android.graphics.Bitmap;  
  5. import  android.graphics.Bitmap.Config;  
  6. import  android.graphics.drawable.BitmapDrawable;  
  7. import  android.os.Bundle;  
  8. import  android.view.View;  
  9. import  android.widget.Button;  
  10. import  android.widget.ImageView;  
  11.   
  12. public   class  testToGray  extends  Activity {  
  13.     /** Called when the activity is first created. */   
  14.     Button btnJAVA,btnNDK;  
  15.     ImageView imgView;  
  16.     @Override   
  17.     public   void  onCreate(Bundle savedInstanceState) {  
  18.         super .onCreate(savedInstanceState);  
  19.         setContentView(R.layout.main);  
  20.         this .setTitle( "使用NDK转换灰度图---hellogv" );  
  21.         btnJAVA=(Button)this .findViewById(R.id.btnJAVA);  
  22.         btnJAVA.setOnClickListener(new  ClickEvent());  
  23.           
  24.         btnNDK=(Button)this .findViewById(R.id.btnNDK);  
  25.         btnNDK.setOnClickListener(new  ClickEvent());  
  26.         imgView=(ImageView)this .findViewById(R.id.ImageView01);  
  27.     }  
  28.     class  ClickEvent  implements  View.OnClickListener{  
  29.   
  30.         @Override   
  31.         public   void  onClick(View v) {  
  32.             if (v==btnJAVA)  
  33.             {  
  34.                 long  current=System.currentTimeMillis();  
  35.                 Bitmap img=ConvertGrayImg(R.drawable.cat);  
  36.                 long  performance=System.currentTimeMillis()-current;  
  37.                 //显示灰度图   
  38.                 imgView.setImageBitmap(img);  
  39.                 testToGray.this .setTitle( "w:" +String.valueOf(img.getWidth())+ ",h:" +String.valueOf(img.getHeight())  
  40.                         +" JAVA耗时 " +String.valueOf(performance)+ " 毫秒" );  
  41.             }  
  42.             else   if (v==btnNDK)  
  43.             {  
  44.                 long  current=System.currentTimeMillis();  
  45.                   
  46.                 //先打开图像并读取像素   
  47.                 Bitmap img1=((BitmapDrawable) getResources().getDrawable(R.drawable.cat)).getBitmap();  
  48.                 int  w=img1.getWidth(),h=img1.getHeight();  
  49.                 int [] pix =  new   int [w * h];  
  50.                 img1.getPixels(pix, 0 , w,  0 0 , w, h);  
  51.                 //通过ImgToGray.so把彩色像素转为灰度像素   
  52.                 int [] resultInt=LibFuns.ImgToGray(pix, w, h);  
  53.                 Bitmap resultImg=Bitmap.createBitmap(w, h, Config.RGB_565);  
  54.                 resultImg.setPixels(resultInt, 0 , w,  0 0 ,w, h);  
  55.                 long  performance=System.currentTimeMillis()-current;  
  56.                 //显示灰度图   
  57.                 imgView.setImageBitmap(resultImg);  
  58.                 testToGray.this .setTitle( "w:" +String.valueOf(img1.getWidth())+ ",h:" +String.valueOf(img1.getHeight())  
  59.                         +" NDK耗时 " +String.valueOf(performance)+ " 毫秒" );  
  60.             }  
  61.         }  
  62.     }  
  63.       
  64.     /**  
  65.      * 把资源图片转为灰度图  
  66.      * @param resID 资源ID  
  67.      * @return  
  68.      */   
  69.     public  Bitmap ConvertGrayImg( int  resID)  
  70.     {  
  71.         Bitmap img1=((BitmapDrawable) getResources().getDrawable(resID)).getBitmap();  
  72.           
  73.         int  w=img1.getWidth(),h=img1.getHeight();  
  74.         int [] pix =  new   int [w * h];  
  75.         img1.getPixels(pix, 0 , w,  0 0 , w, h);  
  76.           
  77.         int  alpha= 0xFF << 24 ;  
  78.         for  ( int  i =  0 ; i < h; i++) {    
  79.             for  ( int  j =  0 ; j < w; j++) {    
  80.                 // 获得像素的颜色     
  81.                 int  color = pix[w * i + j];    
  82.                 int  red = ((color &  0x00FF0000 ) >>  16 );    
  83.                 int  green = ((color &  0x0000FF00 ) >>  8 );    
  84.                 int  blue = color &  0x000000FF ;    
  85.                 color = (red + green + blue)/3 ;    
  86.                 color = alpha | (color << 16 ) | (color <<  8 ) | color;    
  87.                 pix[w * i + j] = color;  
  88.             }  
  89.         }  
  90.         Bitmap result=Bitmap.createBitmap(w, h, Config.RGB_565);  
  91.         result.setPixels(pix, 0 , w,  0 0 ,w, h);  
  92.         return  result;  
  93.     }  
  94. }  

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

  1. package  com.testToGray;  
  2. public   class  LibFuns {  
  3.     static  {  
  4.         System.loadLibrary("ImgToGray" );  
  5.     }  
  6.   
  7.    /**  
  8.     * @param width the current view width  
  9.     * @param height the current view height  
  10.     */   
  11.       
  12.     public   static   native   int [] ImgToGray( int [] buf,  int  w,  int  h);  
  13. }  

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

  1. #include <jni.h>   
  2. #include <stdio.h>   
  3. #include <stdlib.h>   
  4.   
  5. extern   "C"  {  
  6. JNIEXPORT jintArray JNICALL Java_com_testToGray_LibFuns_ImgToGray(  
  7.         JNIEnv* env, jobject obj, jintArray buf, int  w,  int  h);  
  8. }  
  9. ;  
  10.   
  11. JNIEXPORT jintArray JNICALL Java_com_testToGray_LibFuns_ImgToGray(  
  12.         JNIEnv* env, jobject obj, jintArray buf, int  w,  int  h) {  
  13.     jint *cbuf;  
  14.   
  15.     cbuf = env->GetIntArrayElements(buf, false );  
  16.     if  (cbuf == NULL) {  
  17.         return  0;  /* exception occurred */   
  18.     }  
  19.     int  alpha = 0xFF << 24;  
  20.     for  ( int  i = 0; i < h; i++) {  
  21.         for  ( int  j = 0; j < w; j++) {  
  22.             // 获得像素的颜色   
  23.             int  color = cbuf[w * i + j];  
  24.             int  red = ((color & 0x00FF0000) >> 16);  
  25.             int  green = ((color & 0x0000FF00) >> 8);  
  26.             int  blue = color & 0x000000FF;  
  27.             color = (red + green + blue) / 3;  
  28.             color = alpha | (color << 16) | (color << 8) | color;  
  29.             cbuf[w * i + j] = color;  
  30.         }  
  31.     }  
  32.   
  33.     int  size=w * h;  
  34.     jintArray result = env->NewIntArray(size);  
  35.     env->SetIntArrayRegion(result, 0, size, cbuf);  
  36.   
  37.     env->ReleaseIntArrayElements(buf, cbuf, 0);  
  38.   
  39.     return  result;  
  40. }  

Android.mk的源码:

  1. LOCAL_PATH: = $(call my-dir)  
  2.   
  3. include $(CLEAR_VARS)  
  4.   
  5. LOCAL_MODULE    : ImgToGray   
  6. LOCAL_SRC_FILES : ImgToGray .cpp  
  7.   
  8. include $(BUILD_SHARED_LIBRARY)

你可能感兴趣的:(eclipse,android,jni,J#,performance)