/**************************************************************************** * Copyright 2019 Nreal Techonology Limited. All rights reserved. * * This file is part of NRSDK. * * https://www.nreal.ai/ * *****************************************************************************/ using NRKernal.Record; using System; using System.IO; using System.Linq; using UnityEngine; namespace NRKernal.NRExamples { #if UNITY_ANDROID && !UNITY_EDITOR using GalleryDataProvider = NativeGalleryDataProvider; #else using GalleryDataProvider = MockGalleryDataProvider; #endif /// A photo capture example. [HelpURL("https://developer.nreal.ai/develop/unity/video-capture")] public class PhotoCaptureExample : MonoBehaviour { /// The photo capture object. private NRPhotoCapture m_PhotoCaptureObject; /// The camera resolution. private Resolution m_CameraResolution; private bool isOnPhotoProcess = false; GalleryDataProvider galleryDataTool; void Update() { if (NRInput.GetButtonDown(ControllerButton.TRIGGER)) { TakeAPhoto(); } } /// Use this for initialization. void Create(Action onCreated) { if (m_PhotoCaptureObject != null) { NRDebugger.Info("The NRPhotoCapture has already been created."); return; } // Create a PhotoCapture object NRPhotoCapture.CreateAsync(false, delegate (NRPhotoCapture captureObject) { m_CameraResolution = NRPhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First(); if (captureObject == null) { NRDebugger.Error("Can not get a captureObject."); return; } m_PhotoCaptureObject = captureObject; CameraParameters cameraParameters = new CameraParameters(); cameraParameters.cameraResolutionWidth = m_CameraResolution.width; cameraParameters.cameraResolutionHeight = m_CameraResolution.height; cameraParameters.pixelFormat = CapturePixelFormat.BGRA32; cameraParameters.frameRate = NativeConstants.RECORD_FPS_DEFAULT; cameraParameters.blendMode = BlendMode.Blend; // Activate the camera m_PhotoCaptureObject.StartPhotoModeAsync(cameraParameters, delegate (NRPhotoCapture.PhotoCaptureResult result) { NRDebugger.Info("Start PhotoMode Async"); if (result.success) { onCreated?.Invoke(m_PhotoCaptureObject); } else { isOnPhotoProcess = false; this.Close(); NRDebugger.Error("Start PhotoMode faild." + result.resultType); } }, true); }); } /// Take a photo. void TakeAPhoto() { if (isOnPhotoProcess) { NRDebugger.Warning("Currently in the process of taking pictures, Can not take photo ."); return; } isOnPhotoProcess = true; if (m_PhotoCaptureObject == null) { this.Create((capture) => { capture.TakePhotoAsync(OnCapturedPhotoToMemory); }); } else { m_PhotoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory); } } /// Executes the 'captured photo memory' action. /// The result. /// The photo capture frame. void OnCapturedPhotoToMemory(NRPhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame) { var targetTexture = new Texture2D(m_CameraResolution.width, m_CameraResolution.height); // Copy the raw image data into our target texture photoCaptureFrame.UploadImageDataToTexture(targetTexture); // Create a gameobject that we can apply our texture to GameObject quad = GameObject.CreatePrimitive(PrimitiveType.Quad); Renderer quadRenderer = quad.GetComponent() as Renderer; quadRenderer.material = new Material(Resources.Load("Record/Shaders/CaptureScreen")); var headTran = NRSessionManager.Instance.NRHMDPoseTracker.centerAnchor; quad.name = "picture"; quad.transform.localPosition = headTran.position + headTran.forward * 3f; quad.transform.forward = headTran.forward; quad.transform.localScale = new Vector3(1.6f, 0.9f, 0); quadRenderer.material.SetTexture("_MainTex", targetTexture); SaveTextureAsPNG(targetTexture); SaveTextureToGallery(targetTexture); // Release camera resource after capture the photo. this.Close(); } void SaveTextureAsPNG(Texture2D _texture) { try { string filename = string.Format("Nreal_Shot_{0}.png", NRTools.GetTimeStamp().ToString()); string path = string.Format("{0}/NrealShots", Application.persistentDataPath); string filePath = string.Format("{0}/{1}", path, filename); byte[] _bytes = _texture.EncodeToPNG(); NRDebugger.Info("Photo capture: {0}Kb was saved to [{1}]", _bytes.Length / 1024, filePath); if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } File.WriteAllBytes(string.Format("{0}/{1}", path, filename), _bytes); } catch (Exception e) { NRDebugger.Error("Save picture faild!"); throw e; } } /// Closes this object. void Close() { if (m_PhotoCaptureObject == null) { NRDebugger.Error("The NRPhotoCapture has not been created."); return; } // Deactivate our camera m_PhotoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode); } /// Executes the 'stopped photo mode' action. /// The result. void OnStoppedPhotoMode(NRPhotoCapture.PhotoCaptureResult result) { // Shutdown our photo capture resource m_PhotoCaptureObject?.Dispose(); m_PhotoCaptureObject = null; isOnPhotoProcess = false; } /// Executes the 'destroy' action. void OnDestroy() { // Shutdown our photo capture resource m_PhotoCaptureObject?.Dispose(); m_PhotoCaptureObject = null; } public void SaveTextureToGallery(Texture2D _texture) { try { string filename = string.Format("Nreal_Shot_{0}.png", NRTools.GetTimeStamp().ToString()); byte[] _bytes = _texture.EncodeToPNG(); NRDebugger.Info(_bytes.Length / 1024 + "Kb was saved as: " + filename); if (galleryDataTool == null) { galleryDataTool = new GalleryDataProvider(); } galleryDataTool.InsertImage(_bytes, filename, "Screenshots"); } catch (Exception e) { NRDebugger.Error("[TakePicture] Save picture faild!"); throw e; } } } }