/****************************************************************************
* 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;
}
}
}
}