鸟语天空
Hololens 拍照
post by:追风剑情 2023-4-20 19:03

[微软文档] 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
    }
}
评论:
发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容