Files
7d2dXG/Mods/0A-KFCommonUtilityLib/Scripts/Utilities/SaveTextureToFileUtility.cs
Nathaniel Cosford 062dfab2cd Patched
2025-05-30 01:04:40 +09:30

134 lines
5.3 KiB
C#

using Unity.Collections;
using UnityEngine;
using UnityEngine.Rendering;
public class SaveTextureToFileUtility
{
public enum SaveTextureFileFormat
{
EXR, JPG, PNG, TGA
};
/// <summary>
/// Saves a Texture2D to disk with the specified filename and image format
/// </summary>
/// <param name="tex"></param>
/// <param name="filePath"></param>
/// <param name="fileFormat"></param>
/// <param name="jpgQuality"></param>
static public void SaveTexture2DToFile(Texture2D tex, string filePath, SaveTextureFileFormat fileFormat, int jpgQuality = 95)
{
switch (fileFormat)
{
case SaveTextureFileFormat.EXR:
System.IO.File.WriteAllBytes(filePath + ".exr", tex.EncodeToEXR());
break;
case SaveTextureFileFormat.JPG:
System.IO.File.WriteAllBytes(filePath + ".jpg", tex.EncodeToJPG(jpgQuality));
break;
case SaveTextureFileFormat.PNG:
System.IO.File.WriteAllBytes(filePath + ".png", tex.EncodeToPNG());
break;
case SaveTextureFileFormat.TGA:
System.IO.File.WriteAllBytes(filePath + ".tga", tex.EncodeToTGA());
break;
}
}
/// <summary>
/// Saves a RenderTexture to disk with the specified filename and image format
/// </summary>
/// <param name="renderTexture"></param>
/// <param name="filePath"></param>
/// <param name="fileFormat"></param>
/// <param name="jpgQuality"></param>
static public void SaveRenderTextureToFile(RenderTexture renderTexture, string filePath, SaveTextureFileFormat fileFormat = SaveTextureFileFormat.PNG, int jpgQuality = 95)
{
Texture2D tex;
if (fileFormat != SaveTextureFileFormat.EXR)
tex = new Texture2D(renderTexture.width, renderTexture.height, TextureFormat.ARGB32, false, false);
else
tex = new Texture2D(renderTexture.width, renderTexture.height, TextureFormat.RGBAFloat, false, true);
var oldRt = RenderTexture.active;
RenderTexture.active = renderTexture;
tex.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
tex.Apply();
RenderTexture.active = oldRt;
SaveTexture2DToFile(tex, filePath, fileFormat, jpgQuality);
if (Application.isPlaying)
Object.Destroy(tex);
else
Object.DestroyImmediate(tex);
}
static public void SaveTextureToFile(Texture source,
string filePath,
int width,
int height,
SaveTextureFileFormat fileFormat = SaveTextureFileFormat.PNG,
int jpgQuality = 95,
bool asynchronous = true,
System.Action<bool> done = null)
{
// check that the input we're getting is something we can handle:
if (!(source is Texture2D || source is RenderTexture))
{
done?.Invoke(false);
return;
}
// use the original texture size in case the input is negative:
if (width < 0 || height < 0)
{
width = source.width;
height = source.height;
}
// resize the original image:
var resizeRT = RenderTexture.GetTemporary(width, height, 0);
Graphics.Blit(source, resizeRT);
// create a native array to receive data from the GPU:
var narray = new NativeArray<byte>(width * height * 4, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
// request the texture data back from the GPU:
var request = AsyncGPUReadback.RequestIntoNativeArray(ref narray, resizeRT, 0, (AsyncGPUReadbackRequest req) =>
{
// if the readback was successful, encode and write the results to disk
if (!req.hasError)
{
NativeArray<byte> encoded;
switch (fileFormat)
{
case SaveTextureFileFormat.EXR:
encoded = ImageConversion.EncodeNativeArrayToEXR(narray, resizeRT.graphicsFormat, (uint)width, (uint)height);
break;
case SaveTextureFileFormat.JPG:
encoded = ImageConversion.EncodeNativeArrayToJPG(narray, resizeRT.graphicsFormat, (uint)width, (uint)height, 0, jpgQuality);
break;
case SaveTextureFileFormat.TGA:
encoded = ImageConversion.EncodeNativeArrayToTGA(narray, resizeRT.graphicsFormat, (uint)width, (uint)height);
break;
default:
encoded = ImageConversion.EncodeNativeArrayToPNG(narray, resizeRT.graphicsFormat, (uint)width, (uint)height);
break;
}
System.IO.File.WriteAllBytes(filePath, encoded.ToArray());
encoded.Dispose();
}
narray.Dispose();
// notify the user that the operation is done, and its outcome.
done?.Invoke(!req.hasError);
});
if (!asynchronous)
request.WaitForCompletion();
}
}