使用GLSurface繪制相機(jī)預(yù)覽

最近剛剛開始接觸安卓,本著輸出是最好的學(xué)習(xí)的想法,把學(xué)到的技術(shù)點(diǎn)總結(jié)一下。

因?yàn)楣镜囊粋€項(xiàng)目在華為P20手機(jī)上遇到了一個詭異的bug,作為一個剛開始接觸安卓的小白就義不容辭的擔(dān)負(fù)了查找bug的工作。bug現(xiàn)象:從強(qiáng)制橫屏且有渲染相機(jī)的Activity跳轉(zhuǎn)到一個強(qiáng)制豎屏的Activity,然后在返回到相機(jī)的Activity時會有較大的概率發(fā)生一次橫豎屏切換的操作。即相機(jī)的Activity會先扭成豎屏然后在扭成橫屏狀態(tài)。

為了復(fù)現(xiàn)這個問題,我通過GLSurface自己手動渲染了相機(jī)的預(yù)覽,現(xiàn)在通過這篇文章總結(jié)下實(shí)現(xiàn)流程。

涉及到的主要技術(shù)點(diǎn):

1. 請求權(quán)限

2. 使用OpenGLES繪制圖像

3. 打開相機(jī)并繪制相機(jī)畫面

一、請求權(quán)限

請求權(quán)限使用的是別人已經(jīng)封好的一套代碼,還未完整拜讀完,這里先不細(xì)說。值得注意的一點(diǎn)是要申請的權(quán)限需要在AndroidManifest.xml中提前定義。

 <uses-permission  android:name="android.permission.CAMERA"/>

二、使用OpenGLES繪制圖像

首先參考借鑒的文章,感謝前人種樹。

關(guān)于OpenGLES渲染的:https://blog.csdn.net/cassiePython/article/details/51539799

關(guān)于繪制相機(jī)預(yù)覽的:https://zhuanlan.zhihu.com/p/35192609

總體思路:

  1. 需要一個GLSurfaceView,可以直接new,也可以在布局文件中中寫,我用的方式是在布局文件中寫。關(guān)鍵代碼如下:
<android.opengl.GLSurfaceView
        android:id="@+id/gl"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
  1. 為GLSurface函數(shù)設(shè)置渲染版本,添加渲染回調(diào),并設(shè)置渲染方式。主要的渲染工作就在渲染回調(diào)中完成。
        glSurfaceView = findViewById(R.id.gl);
        //設(shè)置渲染GLES版本
        glSurfaceView.setEGLContextClientVersion(2);
        //設(shè)置渲染回調(diào)
        glSurfaceView.setRenderer(new MyRender(this));
        /*渲染方式,RENDERMODE_WHEN_DIRTY表示被動渲染,只有在調(diào)用requestRender或者onResume等方法時才會進(jìn)行渲染。RENDERMODE_CONTINUOUSLY表示持續(xù)渲染*/
        glSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);

  1. 在權(quán)限請求成功后創(chuàng)建打開相機(jī)
        mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
        Camera.Parameters parameters=mCamera.getParameters();
        parameters.set("orientation", "portrait");
        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
        parameters.setPreviewSize(1280, 720);
        mCamera.setDisplayOrientation(90);

        mCamera.setParameters(parameters);
  1. 在onFrameAvailable中請求渲染
    @Override
    public void onFrameAvailable(SurfaceTexture surfaceTexture){
        glSurfaceView.requestRender();
    }
  1. 實(shí)現(xiàn)渲染回調(diào)onRenderer
    public class MyRender implements GLSurfaceView.Renderer{
        private Context context;
        Triangle triangle = null;
        public MyRender(Context context) {
            this.context=context;
        }
        @Override
        public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
            //todo 只運(yùn)行一次
            requestPermission();
            //擦除顏色紅色
            glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
            mOESTextureId = createOESTextureObject();
            //創(chuàng)建一個渲染圖
            mSurfaceTexture = new SurfaceTexture(mOESTextureId);
            //new一個控制GLES渲染的類
            triangle = new Triangle(context);
            try {
                mCamera.setPreviewTexture(mSurfaceTexture);
                mCamera.startPreview();
            } catch (IOException e) {
                e.printStackTrace();
            }
            //添加幀可用監(jiān)聽,通知GLSurface渲染
            mSurfaceTexture.setOnFrameAvailableListener(CameraActivity.this);
        }

        @Override
        public void onSurfaceChanged(GL10 gl10, int width, int height) {
            //todo 渲染窗口大小發(fā)生改變的處理
            Log.e(TAG, "onSurfaceChanged232323232323232 width:" + width + "  height" + height);
            triangle.Change(width, height);
        }


        @Override
        public void onDrawFrame(GL10 gl10) {
            //todo 執(zhí)行渲染工作
            glClear(GL_COLOR_BUFFER_BIT);
            mSurfaceTexture.updateTexImage();
            triangle.draw();
        }
    }
  1. Triangle類的實(shí)現(xiàn)是借用參考鏈接中的實(shí)現(xiàn)做的修改。主要思路是讀取glsl代碼文本編譯并鏈接到程序中,大概流程為Camera->SurfaceTexture->GLES外部紋理->GLSurfaceView

關(guān)鍵綁定代碼:

Camera同SurfaceTexture綁定

mCamera.setPreviewTexture(mSurfaceTexture);

SurfaceTexture同GLES外部紋理綁定

mSurfaceTexture = new SurfaceTexture(mOESTextureId);
 //new一個控制GLES渲染的類
triangle = new Triangle(context);

GLES同GLSurfaceView綁定

glSurfaceView.setRenderer(new MyRender(this));

詳細(xì)工程

sample地址:https://github.com/gggab/DrawCamera

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容