[微软文档] Unity中的照片/视频摄像头
using System;
using System.Collections;
using System.Linq;
using System.IO;
#if WINDOWS_UWP
using Windows.Storage;
#endif
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Windows.WebCam;
/// <summary>
/// 拍照
/// </summary>
public class WebCamPhoto : MonoBehaviour
{
public bool showHolograms = false;
[SerializeField]
private RawImage photoRawImage;
[SerializeField]
private Text debugText;
private Resolution resolution;
private PhotoCapture photoCapture;
private Texture2D photoTexture2D;
//拍照成功事件
public Action<Texture2D> OnPhotoCompleted;
//拍照出错事件
public Action OnPhotoError;
private void Start()
{
//Debug.Log("HoloLens 2 支持的拍照分辨率有:");
//HoloLens 2支持的拍照分辨率为: 3904 x 2196
//获取设备支持的拍照分辨率
//foreach (Resolution res in PhotoCapture.SupportedResolutions)
//{
// Debug.LogFormat("Resolution: width={0}, height={1}", res.width, res.height);
//}
//返回最大分辨率
resolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
}
private void Log(string s)
{
Debug.Log(s);
if (debugText != null)
debugText.text = s;
}
private void LogFormat(string format, params object[] args)
{
Debug.LogFormat(format, args);
if (debugText != null)
debugText.text = string.Format(format, args);
}
// 拍照
public void TakePhoto()
{
if (photoCapture != null)
photoCapture.TakePhotoAsync(OnCapturedToMemory);
else
StartCoroutine(StartCameraCapture());
}
// 启动摄像头
private IEnumerator StartCameraCapture()
{
//检测权限
if (!Application.HasUserAuthorization(UserAuthorization.WebCam))
{
yield return Application.RequestUserAuthorization(UserAuthorization.WebCam);
}
if (Application.HasUserAuthorization(UserAuthorization.WebCam))
{
//第1个参数 true:照片包含全息画面,false:仅硬件摄像头画面
PhotoCapture.CreateAsync(showHolograms, OnCaptureResourceCreated);
}
}
// 创建PhotoCapture对象回调
private void OnCaptureResourceCreated(PhotoCapture captureObject)
{
photoCapture = captureObject;
//设置拍照参数
CameraParameters setupParams = new CameraParameters(WebCamMode.PhotoMode);
setupParams.hologramOpacity = 0.0f;
setupParams.cameraResolutionWidth = resolution.width;
setupParams.cameraResolutionHeight = resolution.height;
setupParams.pixelFormat = CapturePixelFormat.BGRA32;
//开始启动摄像头
photoCapture.StartPhotoModeAsync(setupParams, OnPhotoModeStarted);
}
// 摄像头启动回调
private void OnPhotoModeStarted(PhotoCapture.PhotoCaptureResult result)
{
if (!result.success)
{
Log("启动拍照模式失败");
OnPhotoError?.Invoke();
return;
}
//执行拍照
photoCapture.TakePhotoAsync(OnCapturedToMemory);
}
// 拍照完成回调
private void OnCapturedToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
{
if (!result.success)
{
Log("不能保存照片到内存");
OnPhotoError?.Invoke();
return;
}
//利用照片数据创建新的Texture2D
//List<byte> byteBuffer = new List<byte>();
//setupParams.pixelFormat设置的是什么图片格式,CopyRawImageDataIntoBuffer()方法读出的就是对应格式的图片数据
//photoCaptureFrame.CopyRawImageDataIntoBuffer(byteBuffer);
//photoTexture2D = new Texture2D(resolution.width, resolution.height, TextureFormat.BGRA32, false);
//tex.LoadRawTextureData(byteBuffer.ToArray());
//tex.Apply();
//直接将照片数据赋值给Texture2D
photoTexture2D = new Texture2D(resolution.width, resolution.height, TextureFormat.BGRA32, false);
photoCaptureFrame.UploadImageDataToTexture(photoTexture2D);
if (photoRawImage != null)
photoRawImage.texture = photoTexture2D;
//释放内存中的照片数据
photoCaptureFrame.Dispose();
//停止摄像头
photoCapture.StopPhotoModeAsync(OnPhotoModeStopped);
}
// 停止摄像头回调
private void OnPhotoModeStopped(PhotoCapture.PhotoCaptureResult result)
{
if (result.success)
{
//释放拍照占用的资源
photoCapture.Dispose();
photoCapture = null;
}
Log("拍照完成");
//SavePhoto();
//拍照完成事件
OnPhotoCompleted?.Invoke(photoTexture2D);
}
// 保存照片到 Camera Roll 文件夹
private void SavePhoto()
{
string fileName = "photo.jpg";
string filePath = Path.Combine(Application.persistentDataPath, fileName);
byte[] bytes = photoTexture2D.EncodeToJPG();
File.WriteAllBytes(filePath, bytes);
#if WINDOWS_UWP
//注意:需要勾选上图片库(PicturesLibrary)设备功能,才能访问CameraRoll文件夹
//注意:无法直接保存到CameraRoll文件夹
//注意:HoloLens 2 移动照片时,全息影响会闪烁一下,原因不明
var cameraRollFolder = Windows.Storage.KnownFolders.CameraRoll.Path;
File.Move(filePath, Path.Combine(cameraRollFolder, fileName));
#endif
}
}