`
jandroid
  • 浏览: 1933891 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

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

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

从转换灰度图的耗时来说,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)

分享到:
评论

相关推荐

    Android提高之使用NDK把彩图转换灰度图的方法

    总结来说,使用Android NDK处理图像转换,特别是彩图转灰度图,是一种有效的优化策略。通过编写原生代码,我们可以利用C或C++的强大功能,以更高的效率完成计算密集型任务,为Android应用带来更好的性能表现。

    《Android C++高级编程——使用NDK》_源码.zip

    《Android C++高级编程——使用NDK》提供了Java原生接口(JNI)的概述、Bionic API、POSIX 线程和套接字、C++支持、原生图形和声音API以及NEON/SIMD优化,在一个游戏应用案例的帮助下,你将学到很多关键技能。...

    Android NDK使用Iconv进行编码转换

    Android NDK(Native Development Kit)提供了一种方法来实现这样的编码转换,这就是使用Iconv库。Iconv是一个广泛使用的字符集转换工具,它允许在多种字符编码之间进行转换,包括Unicode、GBK和UTF-8。 Iconv在C/...

    Android C++高级编程:使用NDK(高清完整带书签)电子书

     Android允许应用开发者通过Android原生开发包(NDK)使用诸如C和C++之类的原生代码语言实现他们的部分应用。《移动开发经典丛书·Android C++高级编程:使用NDK》中我们将学习如何用AndroidNDK通过原生代码语言去...

    Android C++高级编程:使用NDK(完整版带书签).pdf

    《Android C++高级编程:使用NDK》是一本深度探讨Android平台上C++开发技术的权威著作,完整版带有书签,方便读者随时查阅和学习。本书主要针对Android开发者,特别是那些希望利用C++来提升应用性能、降低内存占用...

    高清版 Android C++高级编程:使用NDK

    Android C++高级编程:使用NDK

    android-ndk(android-ndk-r25b-linux.zip)

    在Android应用开发中,NDK扮演着至关重要的角色,它允许开发者使用原生代码(如C和C++)来编写部分应用,以提高性能、利用硬件加速功能或复用现有的C/C++库。 1. **JNI(Java Native Interface)**: JNI是Java...

    android-ndk(android-ndk-r23b-windows.zip)

    NDK是Android应用开发中的一个重要组成部分,它允许开发者使用原生代码(如C、C++)来编写部分应用程序,从而利用底层的硬件性能,提高程序运行效率,尤其是在处理图形计算、物理模拟和游戏引擎等高性能需求的场景下...

    Android C++高级编程 使用NDK

    《Android C++高级编程:使用NDK》是一本专注于探讨如何在Android平台上进行C++开发的专业书籍。Android NDK(Native Development Kit)是Google提供的一个工具集,它允许开发者使用原生代码(如C和C++)来编写部分...

    Android C++高级编程:使用NDK_中文-高清带目录

    《Android C++高级编程:使用NDK》是一本专为Android开发者深入理解并掌握NDK技术而编写的书籍。NDK(Native Development Kit)是Google提供的一种工具集,允许开发者在Android平台上使用C和C++编写原生代码,从而...

    android-ndk(android-ndk-r25b-darwin.zip)

    Android NDK,全称为Native Development Kit,是Google提供的一款用于Android平台的C和C++库开发工具集。这个工具允许开发者在Android应用中使用原生代码,以实现高性能计算、图形处理、游戏引擎等复杂功能。`...

    android-ndk(android-ndk-r23b-linux.zip)

    Android NDK,全称为Native Development Kit,是Google提供的一款用于Android平台的C和C++库开发工具集。这个“android-ndk-r23b-linux.zip”文件是NDK的一个特定版本,即r23b,专为Linux操作系统设计。在Android...

    android-ndk(android-ndk-r26b-windows.zip)

    Android NDK,全称为Native Development Kit,是Google提供的一款用于Android平台的C和C++开发工具集。这个压缩包“android-ndk-r26b-windows.zip”包含了NDK的第26个版本,专为Windows操作系统设计。通过这个工具,...

    android-image-filter-ndk,使用android ndk在c中处理位图的android示例项目.zip

    Android NDK(Native Development Kit)是Google提供的一款工具,允许开发者在Android应用中使用原生代码(如C/C++),以提升性能,尤其是处理计算密集型任务,如图像处理。本项目"android-image-filter-ndk"是一个...

    android-ndk(android-ndk-r25b-windows.zip)

    Android NDK,全称为Native Development Kit,是Google提供的一款用于Android平台的C和C++开发工具集。这个压缩包“android-ndk-r25b-windows.zip”包含了NDK的第25个版本,专为Windows操作系统设计。NDK的主要功能...

    Android C++高级编程:使用NDK_Onur Cinar,于红.zip

    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 [ Pro Android C++ with the NDK ]书源码

    《Android C++高级编程使用NDK》是一本深入探讨如何在Android平台上利用C++进行高效开发的专业书籍。这本书源码的提供,对于开发者来说是一份宝贵的参考资料,它涵盖了多个章节的示例代码,帮助读者更好地理解和实践...

    android-ndk(android-ndk-r26b-linux.zip)

    Android NDK,全称为Native Development Kit,是Google提供的一款用于Android平台的开发工具,它允许开发者使用C++和其他原生编程语言编写应用的部分或全部代码。这个“android-ndk-r26b-linux.zip”文件是NDK的一个...

Global site tag (gtag.js) - Google Analytics