解析谷歌camera android-Camera2Basic了解流程

1.工程项目结构解析

  java:我们写Java代码的地方,业务功能都在这里实现
   res:存放我们各种资源文件的地方,有图片,字符串,动画,音频等,还有各种形式的XML文件。

2.代码解析

 🕐 CameraActivity.java

/*
 * Copyright 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.android.camera2basic;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
//   想调用摄像头,必须继承自 OpenCV 的 CameraActivity
public class CameraActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera);
        if (null == savedInstanceState) {
            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.container, Camera2BasicFragment.newInstance())
                    .commit();
        }
    }

}

🕑   AutoFitTextureView.java

/*
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.android.camera2basic;

import android.content.Context;
import android.util.AttributeSet;
import android.view.TextureView;

/**
 * A {@link TextureView} that can be adjusted to a specified aspect ratio.
 *      自定义预览控件
 */
public class AutoFitTextureView extends TextureView {

    private int mRatioWidth = 0;
    private int mRatioHeight = 0;

    public AutoFitTextureView(Context context) {
        this(context, null);
    }

    public AutoFitTextureView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public AutoFitTextureView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    /**
     * Sets the aspect ratio for this view. The size of the view will be measured based on the ratio
     * calculated from the parameters. Note that the actual sizes of parameters don't matter, that
     * is, calling setAspectRatio(2, 3) and setAspectRatio(4, 6) make the same result.
     *
     * @param width  Relative horizontal size
     * @param height Relative vertical size
     *
     *设置此视图的纵横比。视图的大小将根据比率进行测量
     */
    public void setAspectRatio(int width, int height) {
        if (width < 0 || height < 0) {
            throw new IllegalArgumentException("Size cannot be negative.");
        }
        mRatioWidth = width;
        mRatioHeight = height;
        requestLayout();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        if (0 == mRatioWidth || 0 == mRatioHeight) {
            setMeasuredDimension(width, height);
        } else {
            if (width < height * mRatioWidth / mRatioHeight) {
                setMeasuredDimension(width, width * mRatioHeight / mRatioWidth);
            } else {
                setMeasuredDimension(height * mRatioWidth / mRatioHeight, height);
            }
        }
    }

}

该文件 添加一个约束宽高比的方法,设定宽高比后请求系统重新计算布局,实现预览窗口大小的调整。 

经过上述改造,切换相机输出尺寸时,预览窗口会自动调整大小,保持和输出尺寸有相同的宽高比,这样就不会再出现图像拉伸的问题。

而作为重点的就是

Camera2BasicFragment的拍照流程:

1.进入相机,获取TextureView对象,然后开启一个后台线程处理相机数据

2.判断TextureView是否有效,有效就直接openCamera(),无效就加入一个监听SufaceTextureListener,通过回调确保surfaceTexture有效,然后同样openCamera()。

3.设置相机特性setUpCameraOutputs(),设置图片存储监听OnImageAvaliableListener,拍照图片有效会通知ImageSaver线程保存图片,设置AE,AF等。

4.设置矩阵变换 configureTransform()

5.获取CameraManager对象,然后真正通过manager.openCamera打开相机

6.打开相机成功的话,获取CameraDevice,createCameraPreviewSession()用来创建会话,

获得CaptureRequest对象,通过CaptureRequest发送重复请求捕捉画面,开启预览。

7.拍照流程:首先有个入口,拍照按钮点击事件,触发takePicture(),takePicture中实现了lockFocus()锁住焦点。

8.lockFocus():设置了一个等待锁定的状态,发送一次请求,加入了一个回调CaptureCallback,这一步还没有进行拍照。

9.在CaptureCallback的process()中,状态切换为STATE_WAITING_LOCK,进行拍照,当然不一定就是该状态下进行拍照,还要对AE,AF的状态进行判断,最后不管哪个状态下,都会调用captureStillPicture()进行拍照。

10.captureStillPicture() 设置拍照捕捉请求,设置成像方向与预览方向一致,中断停止预览的重复请求,最终进行拍照,拍照数据会由imageSaver处理,保存到文件,然后通过CameraCaptureSession.CaptureCallback回调解除锁定,回复预览界面
 

 Camera API2类的关系

  •     获取系统服务 CameraManager 实例
  •     调用 CameraManager.getCameraCharacteristics() 方法获取 CameraCharacteristics 实例
  •     调用 CameraManager.openCamera() 方法的传入 CameraDevice.StateCallback 方法中获取 CameraDevice 实例
  •     调用 CameraDevice.createCaptureRequest() 方法创建请求会话实例 CaptureRequest.Builder , TEMPLATE_PREVIEW(预览请求), TEMPLATE_STILL_CAPTURE(拍照请求)
  •     调用 CaptureRequest.Builder.addTarget(Surface) 设置 camera2 图像数据的目标 Surface
  •     调用 CameraDevice.createCaptureSession() 创建相机捕获会话,传入 CameraCaptureSession.StateCallback 方法用于拍照或预览
  •     在 CameraCaptureSession.StateCallback 中调用 CaptureRequest.Builder.build() 获取请求会话和 CameraCaptureSession 捕获会话
  •     在 CameraCaptureSession.CaptureCallback 中实现两个抽象方法, onCaptureProgressed(捕获处理)和 onCaptureCompleted(捕获完成)
  •     调用 CameraCaptureSession 发送 CaptureRequest 请求, capture:表示只发一次请求(拍照), setRepeatingRequest:表示不断发送请求(预览)
  •     在 ImageReader.OnImageAvailableListener 监听中回调获取拍照/预览数
     

 

  • 21
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值