将 RawImage 保存到文件
Save a RawImage to file
所以我设置了一个 RawImage
从 VR 耳机的直通摄像头捕获图像。
现在图片显示正确了,我要保存一下...
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);
}
}
}
这给了我
[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
我不知道为什么图像应该是空的。
让我们尝试 Convert Color32 array to byte array to send over network 建议的 Color32
事情:
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;
}
这给了我
[CAMERA_CAPTURE] Trying to get image
[CAMERA_CAPTURE] Texture '' is not configured correctly to allow GetPixels
我还发现 https://answers.unity.com/questions/1503328/save-rawimage-texture-to-file.html 与所有听起来正是您需要但几年前被问到的问题一样,完全没有有用的信息。
我只是想把我正在看的血腥画面保存在护目镜里,这也太难了吧?!
一些帮助将不胜感激。
如何保存 RawImage
?
(注意:texture.GetType().FullName
给我 UnityEngine.Texture2D
)
(注意:我取回后查看了贴图大小,是600x600
所以图片不只是0
像素大)
你可以调用 texture2d.EncodeToJPG 到 texture2D,你做对了。
但是,您不能将任何纹理投射到 texture2D 中。嗯,你可以,但事情不一定会成功,因为你自己想通了;)
要将 RENDERtexture 转换为 Texture2D,您可以执行以下操作:
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;
如果这不起作用,您可以像 derHugo 指出的那样尝试 Graphics.CopyTexture(),或者 google 将您拥有的特定纹理类型转换为 Texture2D
我认为您不能简单地将 RawImage.texture
转换为 Texture2D
。尝试像
这样实际复制它
var texture2d = new Texture2D(texture.width, texture.hight);
Graphics.CopyTexture(texture, texture2d);
Blit 您的图像到 RenderTexture
,然后使用 that 创建一个新的 Texture2D
private static Texture2D GetReadableTexture2d(Texture texture)
{
var tmp = RenderTexture.GetTemporary(
texture.width,
texture.height,
0,
RenderTextureFormat.Default,
RenderTextureReadWrite.Linear
);
Graphics.Blit(texture, tmp);
var previousRenderTexture = RenderTexture.active;
RenderTexture.active = tmp;
var texture2d = new Texture2D(texture.width, texture.height);
texture2d.ReadPixels(new Rect(0, 0, texture.width, texture.height), 0, 0);
texture2d.Apply();
RenderTexture.active = previousRenderTexture;
RenderTexture.ReleaseTemporary(tmp);
return texture2d;
}
结果 Texture2D
然后可以 EncodeToPNG
并保存:
public void SaveImage()
{
SaveImage(GetReadableTexture2d(CameraImage.texture));
}
private static void SaveImage(Texture2D texture)
{
var imageBytes = texture.EncodeToPNG();
if (imageBytes.Length == 0)
{
AndroidHelper.LogCat($"Trying to save empty picture. Abort.", Tag);
return;
}
var filename = DateTime.Now.ToString("yyyyMMddHHmmssffff") + ".png";
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);
}
}
不确定是否有更简单的方法,但至少这个方法似乎可行。
所以我设置了一个 RawImage
从 VR 耳机的直通摄像头捕获图像。
现在图片显示正确了,我要保存一下...
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);
}
}
}
这给了我
[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
我不知道为什么图像应该是空的。
让我们尝试 Convert Color32 array to byte array to send over network 建议的 Color32
事情:
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;
}
这给了我
[CAMERA_CAPTURE] Trying to get image
[CAMERA_CAPTURE] Texture '' is not configured correctly to allow GetPixels
我还发现 https://answers.unity.com/questions/1503328/save-rawimage-texture-to-file.html 与所有听起来正是您需要但几年前被问到的问题一样,完全没有有用的信息。
我只是想把我正在看的血腥画面保存在护目镜里,这也太难了吧?!
一些帮助将不胜感激。
如何保存 RawImage
?
(注意:texture.GetType().FullName
给我 UnityEngine.Texture2D
)
(注意:我取回后查看了贴图大小,是600x600
所以图片不只是0
像素大)
你可以调用 texture2d.EncodeToJPG 到 texture2D,你做对了。 但是,您不能将任何纹理投射到 texture2D 中。嗯,你可以,但事情不一定会成功,因为你自己想通了;)
要将 RENDERtexture 转换为 Texture2D,您可以执行以下操作:
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;
如果这不起作用,您可以像 derHugo 指出的那样尝试 Graphics.CopyTexture(),或者 google 将您拥有的特定纹理类型转换为 Texture2D
我认为您不能简单地将 RawImage.texture
转换为 Texture2D
。尝试像
var texture2d = new Texture2D(texture.width, texture.hight);
Graphics.CopyTexture(texture, texture2d);
Blit 您的图像到 RenderTexture
,然后使用 that 创建一个新的 Texture2D
private static Texture2D GetReadableTexture2d(Texture texture)
{
var tmp = RenderTexture.GetTemporary(
texture.width,
texture.height,
0,
RenderTextureFormat.Default,
RenderTextureReadWrite.Linear
);
Graphics.Blit(texture, tmp);
var previousRenderTexture = RenderTexture.active;
RenderTexture.active = tmp;
var texture2d = new Texture2D(texture.width, texture.height);
texture2d.ReadPixels(new Rect(0, 0, texture.width, texture.height), 0, 0);
texture2d.Apply();
RenderTexture.active = previousRenderTexture;
RenderTexture.ReleaseTemporary(tmp);
return texture2d;
}
结果 Texture2D
然后可以 EncodeToPNG
并保存:
public void SaveImage()
{
SaveImage(GetReadableTexture2d(CameraImage.texture));
}
private static void SaveImage(Texture2D texture)
{
var imageBytes = texture.EncodeToPNG();
if (imageBytes.Length == 0)
{
AndroidHelper.LogCat($"Trying to save empty picture. Abort.", Tag);
return;
}
var filename = DateTime.Now.ToString("yyyyMMddHHmmssffff") + ".png";
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);
}
}
不确定是否有更简单的方法,但至少这个方法似乎可行。