<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 189,comments - 115,trackbacks - 0

    Android 畫圖方式

    Android apk 里面的畫圖分為2D和3D兩種:2D是由Skia 來實現的,也就是我們在框架圖上看到的SGL,SGL也會調用部分opengl 的內容來實現簡單的3D效果;3D部分是由OpenGL|ES實現的,OpenGL|ES是Opengl的嵌入式版本,我們先了解一下Android apk的幾種畫圖方式,然后再來來看一看這一整套的圖形體系是怎么建立的。
    首先畫圖都是針對提供給應用 程序的一塊內存填充數據 , 沒去研究過一個Activity是否就對應著底層的一個surface,但是應該都是對這塊surface內存進行操作。因此說穿了就是我們要么調用2D 的API畫圖,要么調用3D的API畫圖,然后將畫下來的圖保存在這個內存中,最后這個內存里面的內容會被Opengl渲染以后變為可以在屏幕上的像素信 息。

    一 、Apk應用主要關心的還是這些API的使用,在Android apk里面畫圖有2種方式 [2D]:
    1、Simple Graphics in View
    就是直接使用Android已經實現的一些畫圖操作,比如說images,shapes,colors,pre-defined animation等等,這些簡單的畫圖操作實際上是由skia來提供的2D圖形操作。使用這些預定義好的操作,我們可以實現諸如貼一張背景圖啊,畫出簡 單地形狀阿,實現一些簡單的動畫之類的操作。這里的簡單可以這么理解,就是我們在這里沒有一筆一畫地構造出一個圖形出來,我們只是把我們的Graphic 資源放入View體系中,由系統 來將這些Graphic畫出來。舉個例子:我們現在在Activity里面綁定一個ImageView,我們可以設置 這 個ImageView的內容是我們的picture,然后我們可以讓這個picture整體顏色上來點藍色調,然后我們還可以為這個ImageView加 入一個預定義動畫,這樣當系統要顯示這個View的時候就會顯示我們的picture,并且會有動畫,并帶有一個藍色調,我們并沒有自己去定義畫圖操作, 而是將這些內容放入View中,由系統來將這些內容畫出來。這種方式只能畫靜態或者極為簡單的2D圖畫,對于實時性很強的動畫,高品質的游戲都是沒法實現 的。
    2、Canvas
    首先我們要明白這個Canvas是一個2D的概念,是在Skia中定義的。也就是說在這個方式下還是說的畫2D圖形。我們可以把這個Canvas理解成系 統提供給我們的一塊內存區域(但實際上它只是一套畫圖的API,真正的內存是下面的Bitmap),而且它還提供了一整套對這個內存區域進行操作的方法, 所有的這些操作都是畫圖API。也就是說在這種方式下我們已經能一筆一劃或者使用Graphic來畫我們所需要的東西了,要畫什么要顯示什么都由我們自己 控制。這種方式根據環境還分為兩種:一種就是使用普通View的canvas畫圖,還有一種就是使用專門的SurfaceView的canvas來畫圖。 兩種的主要是區別就是可以在SurfaceView中定義一個專門的線程來完成畫圖工作,應用程序不需要等待View的刷圖,提高性能。前面一種適合處理 量比較小,幀率比較小的動畫,比如說象棋游戲之類的;而后一種主要用在游戲,高品質動畫方面的畫圖。下面是這兩種方式的典型sequence :
    2.1、View canvas
    (1)  定義一個自己的View :class your_view extends View{}  ;
    (2)  重載View的onDraw方法:protected void onDraw(Canvas canvas){} ;
    (3)  在onDraw方法中定義你自己的畫圖操作 ;

    ps: 可以定義自己的Btimap:
    Bitmap b = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(b);
    但是必須將這個Bitmap放入View的canvas中,畫的圖才能顯示出來:public void drawBitmap (Bitmap bitmap, Matrix matrix, Paint paint)  ;
    invalidate()這個函數被調用后,系統會在不久的將來重新調用onDraw()函數,這個時間很短但并不是可預知的,我曾經在onDraw() 中寫了一個if語句,利用validate讓系統死循環調用onDraw刷兩張圖,幾乎上這兩張圖是刷在一起的。

    2.2、Surface View Canvas
    (1)  定義一個自己的SurfaceView : class your_surfaceview extends SurfaceView  implements SurfaceHolder.Callback() {}  ;
    (2)  實現SurfaceHolder.Callback的3個方法surfaceCreated()   surfaceChanged()   surfaceDestroyed() ;
    (3)  定義自己的專注于畫圖的線程  : class your_thread extends Thread() {} ;
    (4)  重載線程的run()函數  [一般在run中定義畫圖操作,在surfaceCreated中啟動這個線程]
    (5)  畫圖的過程一般是這樣的:
    SurfaceHolder surfaceHolder = getHolder() ;          //取得holder,這個holder主要是對surface操作的適配,用戶不具備對surface操作的權限
    surfaceHolder.addCallback(this) ;                          //注冊實現好的callback
    Canvas canvas = surfaceHolder.lockCanvas() ;      //取得畫圖的Canvas
    /*---------------------------------畫圖
    **-------------------------------- 畫圖結束*/
    surfaceHolder.unlockCanvasAndPost() ;                //提交并顯示

    所有前面3種方式的畫圖的一些例子在SDK上都有,寫得也比較清楚,我這里就不說了,這里寫一下我調這些代碼過程一些小經驗,應該主要涉及的是Activity這方面,應該以后都用得到:
    首先是關于Eclipse的 :
    (1) ctrl + shift + O 可以自動添加需要的依賴包,這功能挺實用的覺得,還有alt + /是語法補全 ;
    (2) 代碼中右鍵比較實用的功能有很多,我記得的是F3找類的聲明,F4找類的繼承關系 ;
    (3) 斷點調試比較方便的,在Eclipse的右上交可以選擇閱讀代碼的方式,還能經如debug模式,我現在用到的兩個打log的方式:
    Log.e("class", "value : "+ classname) ;    //檢測class是否為空指針
    Log.e(this.getClass().getName(), "notice message") ;
    然后是關于Activity的 :
    (1) 首先盡量把UI的設計放在XML中實現,而不要放在代碼中實現,這樣方便設計,修改和移植 ;
    (2) 所有使用到的component都必須在manifest中聲明,不然程序中找不到相應的conponet的時候會報錯 ;
    (3) 一般每一個Activity都對應于一個類,和一個相應的布局文件xml ;
    (4) 每一個Activity只有使用setContentView()綁定內容后才會顯示,而且你才能從這個內容(比如xml中)獲取到你需要的元素 ;
    (5) res/drawable和res/raw中的元素的區別是drawable中的元素像素可能會被系統優化,而raw中的不會被優化 ;
    (6) 當多個Activity都從res/drawable中獲得同一個元素,如果其中一個修改它的屬性,所有其他的Activity中這個元素的相應屬性都會改變 ;
    (7) res/anim中保存的是動畫相關的xml ;

    下面我們總結以下2D畫圖用到的包 :
    android.view                   //畫圖是在View中進行的
    android.view.animation         //定義了一些簡單的動畫效果Tween Animation 和 Frame. Animation
    android.graphics                  //定義了畫圖比較通用的API,比如canvas,paint,bitmap等
    android.graphics.drawable       //定義了相應的Drawable(可畫的東西),比如說BitmapDrawable,PictureDrawable等
    android.graphics.drawable.shapes          //定義了一些shape

    二、了解了2D,我們再來看看3D的畫圖方式。3D畫圖SDK上講得很簡單,只是提了一個通用的方式,就是繼承一個View,然后在這個View里面獲得 Opengl的句柄進行畫圖,道理應該來說是和2D一樣的,差別就是一個是使用2D的API畫圖,一個是使用3D的。不過因為3D openGl|ES具有一套本身的運行機制,比如渲染的過程控制等,因此Android為我們提供了一個專門的用在3D畫圖上的 GLSurfaceView。這個類被放在一個單獨的包android.opengl里面,其中實現了其他View所不具備的操作:
    (1) 具有OpenGL|ES調用過程中的錯誤跟蹤,檢查工具,這樣就方便了Opengl編程過程的debug ;
    (2) 所有的畫圖是在一個專門的Surface上進行,這個Surface可以最后被組合到android的View體系中 ;
    (3) 它可以根據EGL的配置來選擇自己的buffer類型,比如RGB565,depth=16 (這里有點疑問,SurfaceHolder的類型是SURFACE_TYPE_GPU,內存就是從EGL分配過來的?)
    (4) 所有畫圖的操作都通過render來提供,而且render對Opengl的調用是在一個單獨的線程中
    (5) Opengl的運行周期與Activity的生命周期可以協調
    下面我們再看看利用GLSurface畫3D圖形的一個典型的Sequence
    (1)  選擇你的EGL配置(就是你畫圖需要的buffer類型) [optional] :
    setEGLConfigChooser(boolean)
    setEGLConfigChooser(EGLConfigChooser) 
    setEGLConfigChooser(int, int, int, int, int, int)
    (2) 選擇是否需要Debug信息 [optional] :
    setDebugFlags(int)
    setGLWrapper(GLSurfaceView.GLWrapper).
    (3) 為GLSurfaceView注冊一個畫圖的renderer : setRenderer(GLSurfaceView.Renderer)
    (4) 設置reander mode,可以為持續渲染或者根據命令 來渲染,默認是continuous rendering [optional]: setRenderMode(int)
    這里有一個要注意的地方就是必須將Opengl的運行和Activity的生命周期綁定在一起,也就是說Activity pause的時候,opengl的渲染也必須pause。另外GLSurfaceView還提供了一個非常實用的線程間交互的函數 queueEvent(Runnable),可以用在主線程和render線程之間的交互,下面就是SDK提供的范例:
    class MyGLSurfaceView extends GLSurfaceView {
    private MyRenderer mMyRenderer;
    public void start() {
    mMyRenderer = ...;
    setRenderer(mMyRenderer);
    }
    public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
    queueEvent(new Runnable() {
    // This method will be called on the rendering
    // thread:
    public void run() {
    mMyRenderer.handleDpadCenter();
    }});
    return true;
    }
    return super.onKeyDown(keyCode, event);
    }
    }
    GLSurfaceView是Android提供的一個非常值得學習 的類,它實際上是一個如何在View中添加畫圖線程的例子,如何在Java 中使用線程的例子,如何添加事件隊列的例子,一個使用SurfaceView畫圖的經典Sequence,一個如何定義Debug信息的例子,覺得把它看懂了可以學到很多知識 ,具體的源碼在:/framworks/base/opengl/java/android/opengl/GLSurfaceView.java 。
    3D的內容基本到這里基本講完了,剩下的主要是如何使用Opengl API的問題了,可以看看API demo中簡單的立方體,復雜的可以看看它那個魔方的實現。下面我們總結一下3D畫圖需要用到的包:
    Android.opengl     //主要定義了GLSurfaceView
    javax.microedition.khronos.egl   //java層的egl接口
    javax.microedition.khronos.opengles  //opengl API
     
    三、了解了2D和3D基本的畫圖方法,我們再回過頭來看看整個Android對Opengl和Skia的調用層次關系
    3.1、首先來看2D,2D是主要使用的圖形引擎,畢竟3D受制于其過高的硬件要求在手機上使用還是比較少,而且Skia也能部分實現類似于3D的效果, 因此可以說SKia實現了Android平臺上絕大多數的圖形工作。下面我們來看看從應用層到底層對skia的調用關系:

    Android對skia的調用是一個比較經典 的調用過程,應用程序的幾個包是在SDK中提供的;JNI放在框架的JNI目錄下面的Graphic目錄;skia是作為一個第三方組件放在external目錄下面。我們可以稍微了解一下skia的結構:      
     
    這里主要涉及到的3個庫:
    libcorecg.so  包含/skia/src/core的部分內容,比如其中的Region,Rect是在SurfaceFlinger里面計算可是區域的操作基本單位
    libsgl.so        包含/skia/src/core|effects|images|ports|utils的部分和全部內容,這個實現了skia大部分的圖形效果,以及圖形格式的編解碼
    libskiagl.so   包含/skia/src/gl里面的內容,主要用來調用opengl實現部分效果
    另外我看到/skia/src中有兩個目錄animator和view沒有寫入makefile的編譯路徑中,我覺得這兩個目錄是很重要的,不知道是現在Android還沒使用到,還是用其他的方式加載進去的。
    要想在底層使用skia的接口來畫圖需要全面了解skia的一整套機制,實際上skia開源到現在還沒多久,在網上能找到的資料是也是很粗淺的,如果將來真需要在這方面下功夫肯定是需要一定的工作量的。
    3.2、Android對3D的調用曾經讓我迷惑了一段時間,因為在framewoks/base/core/jni這個目錄一直沒找到跟opengl相 關的內容,后面去仔細看看opengl里面的內容才知道Android把opengl的本地實現,JNI,java接口都放在/frameworks /base/opengl下面了,而且它內部還帶了一個工具可以生成JNI代碼。
     
    我們來看看opengl的目錄結構:
    /include     包含egl和gles所有的頭文件 
    /java/android/opengl   這個目錄包含的就是我們3D畫圖要使用到的GLSurfaceView
    /java/com/google/android/gles_jni   這個目錄包含一些自動生成的文件
    /java/javax/microedition/khronos/egl   這就是應用層使用到的egl接口
    /java/javax/microedition/khronos/opengl  這就是應用層使用到的opengl接口
    /libagl  這個就是opengl主要的實現了
    /libs  這里面包含兩個庫的實現,一個是libegl.so 還有一個是libGL|ES_CM.so
    /tools  在我的理解這就是一個jni的生成工具
    Opengl編程誰都知道是一個大工程,我覺得現在對3D的需求應該是很低的,很多效果我們使用skia也可以實現。所以我覺得將來的重點應該還是放在skia上面。
    posted on 2010-08-30 13:54 MEYE 閱讀(957) 評論(0)  編輯  收藏 所屬分類: Android3D
    主站蜘蛛池模板: 亚洲福利视频网站| 亚洲国产精品高清久久久| 国产色婷婷精品免费视频| 全部免费a级毛片| 中文亚洲AV片不卡在线观看| 亚洲AV色香蕉一区二区| 亚洲一区二区三区久久| 国产精品亚洲专区无码不卡| 久久嫩草影院免费看夜色| 四虎影视成人永久免费观看视频 | 国产高清不卡免费在线| 免费国产黄线在线观看| 亚洲av无码成人精品区| 日韩亚洲人成在线综合日本| 亚洲第一页在线播放| 国产精品亚洲一区二区三区久久 | 高清一区二区三区免费视频| 日韩版码免费福利视频| 免费jjzz在线播放国产| 亚洲一二成人精品区| 亚洲av午夜电影在线观看| 中文字幕成人免费高清在线| 国产精品成人观看视频免费| 免费国产在线观看老王影院| 亚洲国产精品无码专区在线观看| 亚洲一区二区三区免费视频| japanese色国产在线看免费| av无码免费一区二区三区| 国产精品色午夜视频免费看| 亚洲成a人片77777老司机| 亚洲爆乳精品无码一区二区| 久久免费公开视频| 国产成人精品免费直播 | 7777久久亚洲中文字幕蜜桃| 亚洲人成人网站18禁| 免费无码H肉动漫在线观看麻豆 | 亚洲第一页综合图片自拍| 亚洲精选在线观看| 激情小说亚洲色图| 3344免费播放观看视频| 亚洲精品偷拍视频免费观看 |