So I set up a RawImage
that captures the image from a VR headset's pass-through camera.
Now that the picture is correctly displayed, I'd like to save it ...
public class CameraCaptureBehaviour : MonoBehaviour
{
private const string Tag = "[CAMERA_CAPTURE]";
private const int CaptureFrequency = 500;
[field:SerializeField] private RawImage CameraImage { get; set; }
private int count = 0;
private void Update()
{
if ( count % CaptureFrequency != 0) return;
AndroidHelper.LogCat("Trying to get image", Tag);
try
{
SaveImage();
}
catch (Exception e)
{
AndroidHelper.LogCat(e.Message, Tag);
}
}
private void SaveImage()
{
var texture = CameraImage.texture;
if (texture == null)
{
AndroidHelper.LogCat("No camera image found.", Tag);
return;
}
var texture2d = (Texture2D) texture;
var imageBytes = texture2d.EncodeToJPG();
AndroidHelper.LogCat($"imageBytes is null: {imageBytes == null}", Tag);
if (imageBytes == null) return;
var filename = DateTime.Now.ToString("yyyyMMddHHmmssffff") ".jpg";
var filepath = Path.Combine(Application.persistentDataPath, filename);
AndroidHelper.LogCat($"{imageBytes.Length} to {filepath}", Tag);
try
{
File.WriteAllBytes(filepath, imageBytes);
AndroidHelper.LogCat("SAVED", Tag);
}
catch (Exception e)
{
AndroidHelper.LogCat(e.Message, Tag);
}
}
}
which gives me
[CAMERA_CAPTURE] Trying to get image
[CAMERA_CAPTURE] imageBytes is null: False
[CAMERA_CAPTURE] 0 to /storage/emulated/0/Android/data/my.app/files/202203290841482532.png
[CAMERA_CAPTURE] SAVED
I have no idea why the image should be empty.
Let's try the Color32
thing suggested by Convert Color32 array to byte array to send over network :
public class CameraCaptureBehaviour : MonoBehaviour
{
private const string Tag = "[CAMERA_CAPTURE]";
private const int CaptureFrequency = 500;
[field:SerializeField] private RawImage CameraImage { get; set; }
private int count = 0;
private void Update()
{
if ( count % CaptureFrequency != 0) return;
AndroidHelper.LogCat("Trying to get image", Tag);
try
{
SaveImage();
}
catch (Exception e)
{
AndroidHelper.LogCat(e.Message, Tag);
}
}
private void SaveImage()
{
var texture = CameraImage.texture;
if (texture == null)
{
AndroidHelper.LogCat("No camera image found.", Tag);
return;
}
var texture2d = (Texture2D) texture;
var color32 = new Color32Array();
color32.colors = texture2d.GetPixels32();
var imageBytes = color32.byteArray;
AndroidHelper.LogCat($"imageBytes is null: {imageBytes == null}", Tag);
if (imageBytes == null) return;
var filename = DateTime.Now.ToString("yyyyMMddHHmmssffff") ".jpg";
var filepath = Path.Combine(Application.persistentDataPath, filename);
AndroidHelper.LogCat($"{imageBytes.Length} to {filepath}", Tag);
try
{
File.WriteAllBytes(filepath, imageBytes);
AndroidHelper.LogCat("SAVED", Tag);
}
catch (Exception e)
{
AndroidHelper.LogCat(e.Message, Tag);
}
}
}
[StructLayout(LayoutKind.Explicit)]
public struct Color32Array
{
[FieldOffset(0)]
public byte[] byteArray;
[FieldOffset(0)]
public Color32[] colors;
}
which gives me
[CAMERA_CAPTURE] Trying to get image
[CAMERA_CAPTURE] Texture '' is not configured correctly to allow GetPixels
I've also found https://answers.unity.com/questions/1503328/save-rawimage-texture-to-file.html which - like all questions that sound exactly what you need but were asked several years ago - is completely devoid of useful information.
I just want to save the bloody picture I'm looking at in the goggles, that can't be so darn difficult?!
Some help would be appreciated.
How do I save a RawImage
?
(Note: texture.GetType().FullName
gives me UnityEngine.Texture2D
)
(Note: I checked the texture size after I retrieved it, and it's 600x600
so the picture isn't just 0
pixels large)
CodePudding user response:
I don't think you can simply cast the RawImage.texture
to a Texture2D
. Try to rather actually copy it over like e.g.
var texture2d = new Texture2D(texture.width, texture.hight);
Graphics.CopyTexture(texture, texture2d);
CodePudding user response:
You can call texture2d.EncodeToJPG to a texture2D, you got that right. You can NOT however just cast any texture into a texture2D. Well you can, but things won't necessarily work out, as you figured out your self ;)
To convert a RENDERtexture into a Texture2D, you can do the following:
RenderTexture.active = texture;
Texture2D texture2d = new Texture2D(texture.width, texture.height);
texture2d.ReadPixels(new Rect(0, 0, texture.width, texture.height),0, 0);
texture2d.Apply();
RenderTexture.active = null;
If this doesn't work, you can try Graphics.CopyTexture() as derHugo pointed out, or google for the way to convert the specific Texture type you have into a Texture2D