android camera2 封装,Android实现Camera2预览和拍照效果

本文介绍了如何使用Android Camera2 API实现简单的相机预览和拍照功能,包括设置预览尺寸、打开相机、显示预览、拍照及处理焦点锁定等步骤。通过创建CameraDevice.StateCallback和CaptureRequest.Builder来管理和控制相机操作。
摘要由CSDN通过智能技术生成

简介

网上对于 Camera2 的介绍有很多,在 Github 上也有很多关于 Camera2 的封装库,但是对于那些库,封装性太强,有时候我们仅仅是需要个简简单单的拍照功能而已,因此,自定义一个 Camera 使之变得轻量级那是非常重要的了。(本文并非重复造轮子, 而是在于学习 Camera2API 的基本功能, 笔记之。)

学习要点:

使用 Android Camera2 API 的基本功能。

迭代连接到设备的所有相机的特征。

显示相机预览和拍摄照片。

Camera2 API 为连接到 Android 设备的各个相机设备提供了一个界面。 它替代了已弃用的 Camera 类。

使用 getCameraIdList 获取所有可用摄像机的列表。 然后,您可以使用 getCameraCharacteristics,并找到适合您需要的最佳相机(前 / 后面,分辨率等)。

创建一个 CameraDevice.StateCallback 的实例并打开相机。 当相机打开时,准备开始相机预览。

使用 TextureView 显示相机预览。 创建一个 CameraCaptureSession 并设置一个重复的 CaptureRequest。

静像拍摄需要几个步骤。 首先,需要通过更新相机预览的 CaptureRequest 来锁定相机的焦点。

然后,以类似的方式,需要运行一个预捕获序列。之后,它准备拍摄一张照片。 创建一个新的 CaptureRequest 并调用 [capture] 。

完成后,别忘了解锁焦点。

实现效果

192ce4077878ebaccd0382bfcf76caef.png环境

SDK>21

Camera2 类图

620930469833ba0dd35eb19889a49b66.png

0c83ee18611b770549c3271a38a3af0d.png

代码实现

CameraPreview.java

/**

* Created by shenhua on 2017-10-20-0020.

* Email shenhuanet@126.com

*/

public class CameraPreview extends TextureView {

private static final String TAG = "CameraPreview";

private static final SparseIntArray ORIENTATIONS = new SparseIntArray();//从屏幕旋转转换为JPEG方向

private static final int MAX_PREVIEW_WIDTH = 1920;//Camera2 API 保证的最大预览宽高

private static final int MAX_PREVIEW_HEIGHT = 1080;

private static final int STATE_PREVIEW = 0;//显示相机预览

private static final int STATE_WAITING_LOCK = 1;//焦点锁定中

private static final int STATE_WAITING_PRE_CAPTURE = 2;//拍照中

private static final int STATE_WAITING_NON_PRE_CAPTURE = 3;//其它状态

private static final int STATE_PICTURE_TAKEN = 4;//拍照完毕

private int mState = STATE_PREVIEW;

private int mRatioWidth = 0, mRatioHeight = 0;

private int mSensorOrientation;

private boolean mFlashSupported;

private Semaphore mCameraOpenCloseLock = new Semaphore(1);//使用信号量 Semaphore 进行多线程任务调度

private Activity activity;

private File mFile;

private HandlerThread mBackgroundThread;

private Handler mBackgroundHandler;

private Size mPreviewSize;

private String mCameraId;

private CameraDevice mCameraDevice;

private CaptureRequest.Builder mPreviewRequestBuilder;

private CaptureRequest mPreviewRequest;

private CameraCaptureSession mCaptureSession;

private ImageReader mImageReader;

static {

ORIENTATIONS.append(Surface.ROTATION_0, 90);

ORIENTATIONS.append(Surface.ROTATION_90, 0);

ORIENTATIONS.append(Surface.ROTATION_180, 270);

ORIENTATIONS.append(Surface.ROTATION_270, 180);

}

public CameraPreview(Context context) {

this(context, null);

}

public CameraPreview(Context context, AttributeSet attrs) {

this(context, attrs, 0);

}

public CameraPreview(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

mFile = new File(getContext().getExternalFilesDir(null), "pic.jpg");

}

@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);

}

}

}

public void onResume(Activity activity) {

this.activity = activity;

startBackgroundThread();

//当Activity或Fragment OnResume()时,可以冲洗打开一个相机并开始预览,否则,这个Surface已经准备就绪

if (this.isAvailable()) {

openCamera(this.getWidth(), this.getHeight());

} else {

this.setSurfaceTextureListener(mSurfaceTextureListener);

}

}

public void onPause() {

closeCamera();

stopBackgroundThread();

}

public void setOutPutDir(File file) {

this.mFile = file;

}

public void setAspectRatio(int width, int height) {

if (width < 0 || height < 0) {

throw new IllegalArgumentException("Size can't be negative");

}

mRatioWidth = width;

mRatioHeight = height;

requestLayout();

}

public void setAutoFlash(CaptureRequest.Builder requestBuilder) {

if (mFlashSupported) {

requestBuilder.set(CaptureRequest.CONTROL_AE_MODE,

CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);

}

}

public void takePicture() {

lockFocus();

}

private void startBackgroundThread() {

mBackgroundThread = new HandlerThread("Camera

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 使用 camera2 API 可以更加灵活、可定制和高效地完成 Android 相机应用开发,其相比 camera1 API 的性能有大幅提升。 在使用 camera2 API 完成预览拍照前,需要进行以下几个步骤: 1. 获取 CameraManager 对象,查找可用的摄像头列表,并选择需要打开的摄像头。 2. 创建 CameraCaptureSession 对象,用于处理相机触发器的请求,并连接 CameraDevice 和 Surface。 3. 匹配预览和图片输出的 Surface,设置相应的尺寸和格式。 4. 创建 CaptureRequest 对象,设置相应的参数,如自动对焦模式、曝光模式等。 5. 使用 CameraCaptureSession 进行预览拍照。 在预览时,可以使用 TextureView 或 SurfaceView 进行实时数据渲染,比如显示相机预览画面、拍照后处理和显示等,同时可以通过设置监听器动态获取相机输出的图像流数据。 在拍照时,需要创建 ImageReader 对象,设置输出数据的格式和尺寸,同时需要建立对应的 Surface,将其传入 CaptureRequest.Builder,设置请求类型并发起拍照请求。通过设置 ImageReader 的 OnImageAvailableListener 接口,即可接收到图片数据,并进行后续处理和保存。 以上是使用 camera2 API 完成预览拍照的基本流程,实际开发中需要根据具体需求进行优化和调整。 ### 回答2: Android Camera2 API 是 Android 系统中相机功能的一种全新的 API,使用 Camera2 可以更灵活地操作相机设备并获得更高质量的照片。 使用 Camera2 实现预览非常简单,我们只需要实现一个 CameraDevice.StateCallback 接口实现类和一个 SurfaceView 主界面。在 StateCallback 的 onOpened 回调中获得 CameraDevice 的实例,然后通过 ImageReader 创建 SurfaceHolder,最后将 SurfaceHolder 通过 CameraDevice.createCaptureSession 接口跟 CameraDevice 进行绑定即可实现预览拍照实现过程与预览类似,首先获得 CameraDevice 实例,然后创建一个 CaptureRequest.Builder 对象,将拍照设置参数通过 CaptureRequest.Builder.set 方法设置到 CaptureRequest.Builder 对象中,最后通过 CameraCaptureSession.capture 接口启动拍照操作即可。 当然,在使用 Camera2 API 进行操作相机时,还需要注意一些其他问题,比如不同的相机设备有不同的特性,需要针对不同的设备进行优化和适配,还需要保证应用的流畅性和稳定性,以达到更好的用户体验。 总之,使用 Camera2 API 实现预览拍照Android 开发的一个重要技能,需要开发者深入了解该 API 的机制和使用方式,才能更好地实现优秀的相机应用。 ### 回答3: Android中的camera2是一种相机应用程序接口(API),旨在提高相机应用程序的功能和性能。相较于早期版本的camera API,camera2 API提供了更多的控制选项,允许开发者定制相机应用程序的功能,从而实现更好的用户体验。 使用camera2 API实现预览拍照需要以下步骤: 1. 获取CameraManager对象。使用该对象可以获取系统中可用的相机列表,并在需要的时候打开指定相机。 2. 打开指定相机。调用CameraManager.openCamera()方法打开相机。 3. 创建CaptureSession。CaptureSession是与相机关联的一组输出Surface的集合。 4. 创建CaptureRequest。CaptureRequest是一个指定相机操作和设置的重要对象,可以通过它来设置各种模式、参数和目标Surface。 5. 创建Preview Request。处理预览界面。 6. 启动相机预览。启动前,可以使用CaptureRequest.Builder设置其他预览参数。 7. 拍照。当用户点击拍照按钮时,调用CaptureSession.capture()方法,即可拍照并接收回调。 8. 关闭相机。释放所有占用的资源,以便其他应用程序可以使用相机。 总之,在使用camera2 API实现预览拍照时,需要使用许多类和方法。但只要开发者掌握了API中的基本概念和流程,就可以自由地使用该API,设计新型的相机应用程序,提供更好的功能和性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值