自定义相机,使用前置摄像头实现自拍

2024-03-07 12:48

本文主要是介绍自定义相机,使用前置摄像头实现自拍,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

通过Camera.open()获取相机,实现自定义自拍功能。

demo比较简单,直接上代码:

Activity


public class MainActivity extends AppCompatActivity {SurfaceView sView;SurfaceHolder surfaceHodler;int screenWidth, screenHeight;// 定义系统所用的照相机Camera camera;// 是否存在预览中boolean isPreview = false;private String filepath = "";//照片保存路径@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 获取窗口管理器WindowManager wm = getWindowManager();Display display = wm.getDefaultDisplay();DisplayMetrics metrics = new DisplayMetrics();// 获取屏幕的宽和高display.getMetrics(metrics);screenWidth = metrics.widthPixels;screenHeight = metrics.heightPixels;sView = (SurfaceView) findViewById(R.id.sView);// 设置surface不需要自己的维护缓存区sView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);// 获得SurfaceView的SurfaceHoldersurfaceHodler = sView.getHolder();// 为srfaceHolder添加一个回调监听器surfaceHodler.addCallback(new SurfaceHolder.Callback() {@Overridepublic void surfaceDestroyed(SurfaceHolder arg0) {// 如果camera不为null,释放摄像头System.out.println("释放摄像头");if (camera != null) {if (isPreview)camera.stopPreview();camera.release();camera = null;isPreview = false;}}@Overridepublic void surfaceCreated(SurfaceHolder arg0) {System.out.println("打开摄像头");// 打开摄像头initCamera();}@Overridepublic void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2,int arg3) {System.out.println("摄像头改变");}});}public void capture(View source) {sView.setVisibility(View.VISIBLE);}private void initCamera() {if (!isPreview) {// 此处默认打开后置摄像头// 通过传入参数可以打开前置摄像头camera = openFrontFacingCameraGingerbread();}if (!isPreview && camera != null) {Camera.Parameters parameters = camera.getParameters();// 设置预览照片的大小parameters.setPreviewSize(screenWidth, screenHeight);// 设置预览照片时每秒显示多少帧的最小值和最大值parameters.setPreviewFpsRange(4, 10);// 设置照片的格式parameters.setPictureFormat(ImageFormat.JPEG);parameters.setPreviewSize(800, 480);//图片大小// 设置JPG照片的质量parameters.set("jpeg-quality", 100);// 设置照片的大小parameters.setPictureSize(screenWidth, screenHeight);// 通过SurfaceView显示取景画面try {camera.setPreviewDisplay(surfaceHodler);// 系统相机默认是横屏的,我们要旋转90°camera.setDisplayOrientation(90);} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}// 开始预览camera.startPreview();isPreview = true;new Handler().postDelayed(new Runnable() {@Overridepublic void run() {if (camera != null) {System.out.println("控制摄像头自动对焦后才拍摄");// 控制摄像头自动对焦后才拍摄//camera.autoFocus(autoFocusCallback);//关闭声音setCameraSound(true);camera.takePicture(new Camera.ShutterCallback() {@Overridepublic void onShutter() {// 按下快门瞬间会执行此处代码}}, new Camera.PictureCallback() {@Overridepublic void onPictureTaken(byte[] arg0, Camera arg1) {// 此处代码可以决定是否需要保存原始照片信息}}, jpeg);}}}, 1000);}}private Camera openFrontFacingCameraGingerbread() {int cameraCount = 0;Camera cam = null;Camera.CameraInfo cameraInfo = new Camera.CameraInfo();cameraCount = Camera.getNumberOfCameras();System.out.println("cameraCount = "+cameraCount);for (int camIdx = 0; camIdx < cameraCount; camIdx++) {Camera.getCameraInfo(camIdx, cameraInfo);if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {try {cam = Camera.open(camIdx);} catch (RuntimeException e) {Log.e("", "Camera failed to open: " + e.getLocalizedMessage());}}}System.out.println("获取摄像头");if (cam == null)System.out.println("摄像头获取失败");return cam;}Camera.AutoFocusCallback autoFocusCallback = new Camera.AutoFocusCallback() {@Overridepublic void onAutoFocus(boolean arg0, Camera arg1) {if (arg0) {//关闭声音setCameraSound(true);// takePicture()方法需要传入三个监听参数// 第一个监听器;当用户按下快门时激发该监听器// 第二个监听器;当相机获取原始照片时激发该监听器// 第三个监听器;当相机获取JPG照片时激发该监听器System.out.println("拍照");camera.takePicture(new Camera.ShutterCallback() {@Overridepublic void onShutter() {// 按下快门瞬间会执行此处代码}}, new Camera.PictureCallback() {@Overridepublic void onPictureTaken(byte[] arg0, Camera arg1) {// 此处代码可以决定是否需要保存原始照片信息}}, jpeg);new Handler().postDelayed(new Runnable() {@Overridepublic void run() {//  sView.setVisibility(View.GONE);//}}, 1000);} else {System.out.println("对焦失败,不拍照");}}};//创建jpeg图片回调数据对象Camera.PictureCallback jpeg = new Camera.PictureCallback() {@Overridepublic void onPictureTaken(byte[] data, Camera camera) {// TODO Auto-generated method stubtry {Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);// 创建一个位于SD卡上的文件File file = new File(Environment.getExternalStorageDirectory() + File.separator + "aaa");if (!file.exists()) {file.mkdir();}file = new File(file, System.currentTimeMillis() + ".jpg");FileOutputStream fileOutStream = null;try {fileOutStream = new FileOutputStream(file);//把位图输出到指定的文件中bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fileOutStream);fileOutStream.close();} catch (IOException io) {io.printStackTrace();}camera.stopPreview();//关闭预览 处理数据camera.startPreview();//数据处理完后继续开始预览bitmap.recycle();//回收bitmap空间isPreview = true;//关闭预览框,回复声音sView.setVisibility(View.GONE);setCameraSound(false);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}};private void setCameraSound(final boolean isSound) {new Thread(new Runnable() {@Overridepublic void run() {AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);audioManager.setStreamMute(AudioManager.STREAM_SYSTEM, isSound);}}).start();}
}

XML

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context="com.jin.activity.MainActivity"><SurfaceView
        android:id="@+id/sView"android:layout_width="80dp"android:layout_height="100dp"android:layout_alignParentRight="true"android:visibility="gone"></SurfaceView><Button
        android:id="@+id/take"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:onClick="capture"android:text="开门"></Button></RelativeLayout>

注:
经过测试发现7.0以下手机没问题,而7.0系统手机在Camera.open()出现Camera failed to open: Fail to connect to camera service,就是获取不到相机服务无法打开相机,需要手动在手机设置里面打开相机权限,即可正常使用。因此可以加一个判断:

//判断系统版本大于23,即247.0)和以上版本提示打开权限if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {}

这篇关于自定义相机,使用前置摄像头实现自拍的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/783571

相关文章

基于Python实现一个图片拆分工具

《基于Python实现一个图片拆分工具》这篇文章主要为大家详细介绍了如何基于Python实现一个图片拆分工具,可以根据需要的行数和列数进行拆分,感兴趣的小伙伴可以跟随小编一起学习一下... 简单介绍先自己选择输入的图片,默认是输出到项目文件夹中,可以自己选择其他的文件夹,选择需要拆分的行数和列数,可以通过

Python中将嵌套列表扁平化的多种实现方法

《Python中将嵌套列表扁平化的多种实现方法》在Python编程中,我们常常会遇到需要将嵌套列表(即列表中包含列表)转换为一个一维的扁平列表的需求,本文将给大家介绍了多种实现这一目标的方法,需要的朋... 目录python中将嵌套列表扁平化的方法技术背景实现步骤1. 使用嵌套列表推导式2. 使用itert

使用Docker构建Python Flask程序的详细教程

《使用Docker构建PythonFlask程序的详细教程》在当今的软件开发领域,容器化技术正变得越来越流行,而Docker无疑是其中的佼佼者,本文我们就来聊聊如何使用Docker构建一个简单的Py... 目录引言一、准备工作二、创建 Flask 应用程序三、创建 dockerfile四、构建 Docker

Python使用vllm处理多模态数据的预处理技巧

《Python使用vllm处理多模态数据的预处理技巧》本文深入探讨了在Python环境下使用vLLM处理多模态数据的预处理技巧,我们将从基础概念出发,详细讲解文本、图像、音频等多模态数据的预处理方法,... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

Python使用pip工具实现包自动更新的多种方法

《Python使用pip工具实现包自动更新的多种方法》本文深入探讨了使用Python的pip工具实现包自动更新的各种方法和技术,我们将从基础概念开始,逐步介绍手动更新方法、自动化脚本编写、结合CI/C... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

在Linux中改变echo输出颜色的实现方法

《在Linux中改变echo输出颜色的实现方法》在Linux系统的命令行环境下,为了使输出信息更加清晰、突出,便于用户快速识别和区分不同类型的信息,常常需要改变echo命令的输出颜色,所以本文给大家介... 目python录在linux中改变echo输出颜色的方法技术背景实现步骤使用ANSI转义码使用tpu

Conda与Python venv虚拟环境的区别与使用方法详解

《Conda与Pythonvenv虚拟环境的区别与使用方法详解》随着Python社区的成长,虚拟环境的概念和技术也在不断发展,:本文主要介绍Conda与Pythonvenv虚拟环境的区别与使用... 目录前言一、Conda 与 python venv 的核心区别1. Conda 的特点2. Python v

Spring Boot中WebSocket常用使用方法详解

《SpringBoot中WebSocket常用使用方法详解》本文从WebSocket的基础概念出发,详细介绍了SpringBoot集成WebSocket的步骤,并重点讲解了常用的使用方法,包括简单消... 目录一、WebSocket基础概念1.1 什么是WebSocket1.2 WebSocket与HTTP

C#中Guid类使用小结

《C#中Guid类使用小结》本文主要介绍了C#中Guid类用于生成和操作128位的唯一标识符,用于数据库主键及分布式系统,支持通过NewGuid、Parse等方法生成,感兴趣的可以了解一下... 目录前言一、什么是 Guid二、生成 Guid1. 使用 Guid.NewGuid() 方法2. 从字符串创建

Python使用python-can实现合并BLF文件

《Python使用python-can实现合并BLF文件》python-can库是Python生态中专注于CAN总线通信与数据处理的强大工具,本文将使用python-can为BLF文件合并提供高效灵活... 目录一、python-can 库:CAN 数据处理的利器二、BLF 文件合并核心代码解析1. 基础合