Android Camera 正方形预览(二)

来源:互联网 发布:sqlserver删除历史数据 编辑:程序博客网 时间:2024/06/05 09:42

一、概述

为实现Camera正方形预览,本Demo使用GLSurfaceView显示Camera预览数据,本文也主要针对GLSurfaceView的使用做介绍。
Android中的视图有View、SurfaceView、GLSurfaceView、TextureView等,它们各有不同。主要的特点如下:

View:

显示视图,内置画布,提供图形绘制函数、触屏事件、按键事件函数等;
必须在UI主线程内更新画面,速度较慢

SurfaceView:

从Android 1.0(API level 1)时就有 。它继承自类View,因此它本质上是一个View。但与普通View不同的是,它有自己的Surface。
基于View视图进行拓展的视图类,更适合2D游戏的开发;
是View的子类,采用双缓机制,在新的线程中更新画面,所以刷新界面速度比View快,而且不影响主线程对事件的相应;
缺点是不能做变形和动作,也不能随屏幕的变化而变化,也不能在起上面覆盖其他的SurfaceView,导致无法实现滤镜等功能。

GLSurfaceView:

从Android1.5(API level 3)开始加入,作为SurfaceView的补充。 在SurfaceView的基础上,加入了OpenGL ES的管理,并自带了Render渲染线程。
专用于3D游侠开发,适合OpenGL ES专用。

TextureView:

在4.0(API level 14)中引入。它可以将内容流直接投影到View中,可以用于实现Live preview等功能。继承自View,只能运行在硬件加速窗口。
类似于SurfaceView + SurfaceTexture,内部包含一个SurfaceTexture,可以让Camera 的数据和显示分离。 比如需要做二次处理时,如Camera把采集的数据发送给SurfaceTexture(滤镜、美颜),SurfaceTexture处理后传给TextureView显示,TextureView可以做View的变形和动画。
数据处理一般是在主线程上面做。

二、GLSurfaceView使用

1、 创建GLSurfaceView实例,展示数据

@1.1 实例化GLSurfaceView
@1.2 实例化Camera
@1.3 绑定Camera和GLSurfaceView,用于数据显示
    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);                // @1.1 创建GLSurfaceView        mGLSurfaceView = new SquareGLSurfaceView(this);                DisplayMetrics dm = new DisplayMetrics();        mCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;        // @1.2 实例化Camera,后面绑定到GLSurfaceView上面,用于显示数据        mCamera = new SquareCamera(this);        if (!mCamera.openCamera(dm.widthPixels, dm.heightPixels, mCameraId)) {            return;        }        // @1.3 绑定Camera和GLSurfaceView,用于数据显示        mGLSurfaceView.initGLSView(mCamera, false);        setContentView(mGLSurfaceView);    }

1.1 实例化GLSurfaceView

public class SquareGLSurfaceView extends GLSurfaceView {    private static final String TAG = "CameraV1GLSurfaceView";    private SquareRenderer mRenderer;    private int textureId = -1;    public SquareGLSurfaceView(Context context) {        super(context);    }

1.2 实例化Camera

主要是在SquareCamera 中完成的,返回一个Camera实例就好
这个类中,还要定义一些Camera的基本操作,例如startPreView()、stopPreview()等等
import android.app.Activity;import android.graphics.SurfaceTexture;import android.hardware.Camera;import android.util.Log;import android.view.Surface;import java.io.IOException;/** * Created by GHC on 2017/6/27. */public class SquareCamera {    private Activity mActivity;    private int mCameraId;    private Camera mCamera;    public SquareCamera(Activity activity) {        mActivity = activity;    }    // 打开Camera,需要设置Camera的参数,例如预览大小、拍照大小等等。    public boolean openCamera(int screenWidth, int screenHeight, int cameraId) {        try {            mCameraId = cameraId;            mCamera = Camera.open(mCameraId);            Camera.Parameters parameters = mCamera.getParameters();            parameters.setPreviewSize(1280, 720);            setCameraDisplayOrientation(mActivity, mCameraId, mCamera);            mCamera.setParameters(parameters);                  } catch (Exception e) {            e.printStackTrace();            return false;        }        return true;    }    public static void setCameraDisplayOrientation(Activity activity,                                                   int cameraId, Camera camera) {        Camera.CameraInfo info =                new Camera.CameraInfo();        Camera.getCameraInfo(cameraId, info);        int rotation = activity.getWindowManager().getDefaultDisplay()                .getRotation();        int degrees = 0;        switch (rotation) {            case Surface.ROTATION_0: degrees = 0; break;            case Surface.ROTATION_90: degrees = 90; break;            case Surface.ROTATION_180: degrees = 180; break;            case Surface.ROTATION_270: degrees = 270; break;        }        int result;        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {            result = (info.orientation + degrees) % 360;            result = (360 - result) % 360;  // compensate the mirror        } else {  // back-facing            result = (info.orientation - degrees + 360) % 360;        }        camera.setDisplayOrientation(result);    }    public void startPreview() {        if (mCamera != null) {            mCamera.startPreview();        }    }    public void stopPreview() {        if (mCamera != null) {            mCamera.stopPreview();        }    }    public void setPreviewTexture(SurfaceTexture surfaceTexture) {        if (mCamera != null) {            try {                mCamera.setPreviewTexture(surfaceTexture);            } catch (IOException e) {                e.printStackTrace();            }        }    }    public void releaseCamera() {        if (mCamera != null) {            mCamera.release();            mCamera = null;        }    }}

1.3 绑定Camera和GLSurfaceView,用于数据显示

@1.1.1 设置OpenGl ES版本号
@1.1.2 创建Render渲染器
public void initGLSView(SquareCamera camera, boolean isPreviewStarted) {        WindowManager wm = (WindowManager) getContext()                .getSystemService(Context.WINDOW_SERVICE);        int width = wm.getDefaultDisplay().getWidth();        Log.d(TAG, "[initGLSView] >> width:" + width);        //@1.1.1 设置OpenGl ES版本,一般设置为2,适配性比较好        setEGLContextClientVersion(2);        //@1.1.2 设置GLSurfaceView使用的Render渲染器        mRenderer = new SquareRenderer();        mRenderer.init(this, camera, isPreviewStarted, width);        setRenderer(mRenderer);    }

2、Render渲染器的使用

GLSurfaceView创建成功后,就可以在Camera上面查看显示的数据了
之前说过,GLSurfaceView通过子线程来更新画面,其实就是Render渲染线程

2.1 Override方法复写
继承GLSurfaceView.Renderer后,需要复写一下三个方法:

onSurfaceCreated(GL10 gl, EGLConfig config)onSurfaceChanged(GL10 gl, int width, int height)onDrawFrame(GL10 gl)