Android相机(Camera)使用总结及代码示例

本文详细介绍了Android中Camera API的使用,包括设置参数、捕获图像、预览画面等关键步骤,并提供了一系列代码示例,帮助开发者实现相机功能集成到自己的应用中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#.Android中Camera1使用主要流程:
开启相机使用的关键步骤:
0.获取相应权限
1.检查相机可用性
2.遍历相机列表,打开指定方向(前置/后置)相机,获取对应实例对象
3.设置预览参数
4.设置预览画面偏转方向
5.设置预览画面输出方式
6.开启预览
结束相机使用的关键步骤:
1.关闭对应相机预览
2.释放对应相机资源
##.一些要点
1.摄像头相关回调执行的线程
Camera.open([index])会启动相应的摄像头,并返回其实例对象。该方法在哪个线程调用,意味着摄像头将被哪个线程占用和绑定,后继的回调都会在该线程中调用。
2.可以通过设置帧回调接口,获取相机传回的帧画面,来做自己的处理。
private final int PREVIEW_BUFFER_COUNT = 3;
private byte[][] mPreviewCallbackBuffer;
private void otherApiExplain(){
    //方式1:设置回调接口,每当相机有新生成的帧画面,都会自动创建缓冲区,并将画面数据回调
    //          但是会频繁的创建缓冲区和GC销毁,会有较高内存消耗,并不推荐该方式
    mCamera.setPreviewCallback(new Camera.PreviewCallback() {
        @Override
        public void onPreviewFrame(byte[] data, Camera camera) {
            //这里面的Bytes的数据就是NV21格式的数据,或者YUV_420_888的数据
        }
    });
    //方式2:设置该接口,只会回调一次,可用于拍照。会自动创建缓冲区,并将画面数据回调
    mCamera.setOneShotPreviewCallback(new Camera.PreviewCallback() {
        @Override
        public void onPreviewFrame(byte[] data, Camera camera) {
            //这里面的Bytes的数据就是NV21格式的数据,或者YUV_420_888的数据
        }
    });

    //方式3:设置带缓冲区的回调接口。推荐的方式
    //   需要自己addCallbackBuffer()把缓冲区数组传入缓冲区队列,相机画面会存储在这些缓冲区中回调回来;
    //   每次回调,都会从队列取出一个缓冲区数组;当缓冲区队列中没有数组时,就不再继续回调。
    //   因此,可以在每次回调时,都把返回的数据缓冲区,重新放回缓冲区队列中。
    //   这样可以有效复用这些缓冲区,降低内存消耗。  
    if (mPreviewCallbackBuffer == null) {
        // nv21 一个像素点1.5byte
        mPreviewCallbackBuffer = new byte[PREVIEW_BUFFER_COUNT][DESIRED_WIDTH * DESIRED_HEIGHT * 3 / 2];
    }
    // 加入预先生成的指定数量预览缓冲buffer,这里是3个
    for (int i = 0; i < PREVIEW_BUFFER_COUNT; i++){
        mCamera.addCallbackBuffer(mPreviewCallbackBuffer[i]);
    }
    mCamera.setPreviewCallbackWithBuffer(new Camera.PreviewCallback() {
        @Override
        public void onPreviewFrame(byte[] data, Camera camera) {
            //如果这里做费时的操作的话,最好优先把缓冲区放回去,再进行处理
            //  以免队列中缓冲区暂时耗尽,不再回调
        }
    });
}
3.设置预览画面输出的两种方式
//设置预览画面输出方式
//    也可以不设置,而是通过setPreviewCallbackWithBuffer()等方式来获取相机预览画面帧。
//方式1:输出到一个SurfaceView的Surface上,
//     这种方式新的画面帧一旦生成,就会被绘制到SurfaceView的Surface上显示出来
mCamera.setPreviewDisplay(surfaceView.getHolder());

//方式2:输出到SurfaceTexture的缓冲区上,会被转化为一个OpenGl纹理
//      SurfaceTexture通过调用updateTexImage()可以用画面流中最新的画面来更新纹理的内容
//      然后开发者可以将这个纹理做自己需要的业务处理。
//      例如用OpenGl进一步处理后显示到GlSurfaceView上,或者编码到直播视频流中。
//      可通过SurfaceTexture的API:getTransformMatrix(矩阵),来获取纹理采样坐标的变换矩阵;  
mCamera.setPreviewTexture(SurfaceTexture);
4.关于预览中途手机画面方向旋转后,摄像头预览画面旋转角度变化的处理
4.1 手机预览中途,也可以通过调用 mCamera .setDisplayOrientation(result) 来重新设置预览画面的偏转角度。
这一步很简单,只需要重新获取当前画面的旋转角度,然后计算预览画面的应偏转角度并设置就可以了。
4.2 其实有些麻烦的是,动态监听手机画面方向发生了变化。一般容易想到的是下面方法1和方法2两种方法,但都有一定问题。
    自己想的方法是,添加一个每个1s执行1次的循环,每次都检查方向是够改变,再结合方法2,来监听方向改变,即下面的方法3。
###方法1,该方法不可取。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值