Skip to content

Instantly share code, notes, and snippets.

@Raveler
Created June 15, 2023 13:28
Show Gist options
  • Save Raveler/787da5e901677f76118cb89d092e247d to your computer and use it in GitHub Desktop.
Save Raveler/787da5e901677f76118cb89d092e247d to your computer and use it in GitHub Desktop.
using UnityEngine;
using System.IO;
using System;
public static class RenderTextureExtensions
{
private static DefaultDictionary<RenderTexture, Texture2D> _cachedTextures = new DefaultDictionary<RenderTexture, Texture2D>();
public static Texture2D GetTexture(this RenderTexture renderTexture)
{
var tex = new Texture2D(renderTexture.width, renderTexture.height, TextureFormat.ARGB32, false);
_cachedTextures[renderTexture] = tex;
var prevRenderTexture = RenderTexture.active;
RenderTexture.active = renderTexture;
tex.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
tex.Apply();
RenderTexture.active = prevRenderTexture;
return tex;
}
public static Texture2D GetTextureRGBA32(this RenderTexture renderTexture)
{
var tex = new Texture2D(renderTexture.width, renderTexture.height, TextureFormat.RGBA32, false);
_cachedTextures[renderTexture] = tex;
var prevRenderTexture = RenderTexture.active;
RenderTexture.active = renderTexture;
tex.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
tex.Apply();
RenderTexture.active = prevRenderTexture;
return tex;
}
public static Texture2D GetTextureWithoutAlpha(this RenderTexture renderTexture)
{
var tex = new Texture2D(renderTexture.width, renderTexture.height, TextureFormat.RGB24, false);
_cachedTextures[renderTexture] = tex;
RenderTexture.active = renderTexture;
tex.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
tex.Apply();
return tex;
}
public static void SaveAs(this RenderTexture renderTexture, string fileName)
{
if (renderTexture.format != RenderTextureFormat.ARGB32) throw new ArgumentException("The format for the render texture must be ARGB32.");
// convert to a texture
Texture2D tex = _cachedTextures[renderTexture];
if (tex == null) tex = renderTexture.GetTexture();
else
{
var prevRenderTexture = RenderTexture.active;
RenderTexture.active = renderTexture;
tex.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
tex.Apply();
RenderTexture.active = prevRenderTexture;
}
// save the texture
tex.SaveAs(fileName);
//GameObject.Destroy(tex);
}
public static byte[] EncodeAsImage(this Texture2D tex, string fileName)
{
byte[] bytes = null;
if (fileName.ToLower().EndsWith("png")) bytes = tex.EncodeToPNG();
else if (fileName.ToLower().EndsWith("jpg") || fileName.ToLower().EndsWith("jpeg")) bytes = tex.EncodeToJPG(90);
else throw new ArgumentException("File DisplayName with extension " + fileName + " not supported. Please use png or jpg.");
return bytes;
}
public static void SaveAs(this Texture2D tex, string fileName)
{
var bytes = EncodeAsImage(tex, fileName);
string dir = Path.GetDirectoryName(fileName);
if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) PathExt.EnsureDirectory(dir);
File.WriteAllBytes(fileName, bytes);
}
public static void SaveAsWithMaximumFileSize(this Texture2D tex, string fileName, int maxFileSizeInBytes, int startQuality = 95)
{
byte[] bytes = null;
if (fileName.ToLower().EndsWith("png"))
{
bytes = tex.EncodeToPNG();
if (bytes.Length > maxFileSizeInBytes) throw new ArgumentException($"Cannot compress the texture into a PNG of size {maxFileSizeInBytes}, compressed size is {bytes.Length}.");
}
else if (fileName.ToLower().EndsWith("jpg") || fileName.ToLower().EndsWith("jpeg"))
{
int quality = startQuality;
while (quality > 0)
{
bytes = tex.EncodeToJPG(quality);
if (bytes.Length <= maxFileSizeInBytes) break;
else quality -= 5;
}
if (quality == 0) throw new ArgumentException($"Failed to compress image to JPEG: even the lowest quality setting compresses to {bytes.Length}, which is more than the required {maxFileSizeInBytes}.");
}
else throw new ArgumentException("File DisplayName with extension " + fileName + " not supported. Please use png or jpg.");
string dir = Path.GetDirectoryName(fileName);
if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) PathExt.EnsureDirectory(dir);
File.WriteAllBytes(fileName, bytes);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment