// SPDX-FileCopyrightText: 2023 Unity Technologies and the glTFast authors
// SPDX-License-Identifier: Apache-2.0
using System;
using UnityEngine;
using UnityEngine.Assertions;
#if UNITY_2022_1_OR_NEWER
using UnityEngine.Experimental.Rendering;
#endif
using Object = UnityEngine.Object;
namespace GLTFast.Export
{
///
/// Wrapper to export a glTF image from one or more Unity textures
///
public abstract class ImageExportBase
{
///
/// Exported texture's file name
///
public abstract string FileName { get; }
///
/// Exported texture's mime type
///
public abstract string MimeType { get; }
///
/// Source texture's filter mode
///
public abstract FilterMode FilterMode { get; }
///
/// Source texture's wrap mode (U direction)
///
public abstract TextureWrapMode WrapModeU { get; }
///
/// Source texture's wrap mode (V direction)
///
public abstract TextureWrapMode WrapModeV { get; }
///
/// Writes image file
///
/// Destination file path
/// If true, existing files will be overwritten
/// True if writing succeeded, false otherwise
public abstract bool Write(string filePath, bool overwrite);
///
/// Returns the exported and encoded texture data
///
/// Encoded texture data.
public abstract byte[] GetData();
///
/// [1-100] quality for JPG images
///
public int JpgQuality { get; set; } = 60;
///
/// Encodes the export texture
///
/// Main texture to encode
/// Image format
/// [1-100] quality for JPG images
/// True if the texture has an alpha channel
/// Custom blit material
/// Encoded texture data
protected static byte[] EncodeTexture(
Texture2D texture,
ImageFormat format,
int jpgQuality,
bool hasAlpha = true,
Material blitMaterial = null)
{
#if UNITY_IMAGECONVERSION
Assert.IsNotNull(texture);
Texture2D exportTexture;
var tmpTexture = false;
if (texture.isReadable && blitMaterial==null) {
exportTexture = texture;
} else {
var destRenderTexture = RenderTexture.GetTemporary(
texture.width,
texture.height,
0,
RenderTextureFormat.ARGB32,
RenderTextureReadWrite.Linear,
1,
RenderTextureMemoryless.Depth
);
if (blitMaterial == null) {
Graphics.Blit(texture, destRenderTexture);
} else {
Graphics.Blit(texture, destRenderTexture, blitMaterial);
}
exportTexture = new Texture2D(
texture.width,
texture.height,
#if UNITY_2023_2_OR_NEWER
// ~20 times faster texture construction
!hasAlpha && SystemInfo.IsFormatSupported(GraphicsFormat.R8G8B8_UNorm, GraphicsFormatUsage.Sample) ? GraphicsFormat.R8G8B8_UNorm : GraphicsFormat.R8G8B8A8_UNorm,
TextureCreationFlags.DontInitializePixels | TextureCreationFlags.DontUploadUponCreate
#elif UNITY_2022_1_OR_NEWER
// ~20 times faster texture construction
!hasAlpha && SystemInfo.IsFormatSupported(GraphicsFormat.R8G8B8_UNorm, FormatUsage.Sample) ? GraphicsFormat.R8G8B8_UNorm : GraphicsFormat.R8G8B8A8_UNorm,
TextureCreationFlags.DontInitializePixels | TextureCreationFlags.DontUploadUponCreate
#else
hasAlpha ? TextureFormat.ARGB32 : TextureFormat.RGB24,
false,
true
#endif
);
exportTexture.ReadPixels(new Rect(0, 0, destRenderTexture.width, destRenderTexture.height), 0, 0);
RenderTexture.ReleaseTemporary(destRenderTexture);
exportTexture.Apply();
tmpTexture = true;
}
var imageData = format == ImageFormat.Png
? exportTexture.EncodeToPNG()
: exportTexture.EncodeToJPG(jpgQuality);
if (tmpTexture) {
// Release temporary texture
#if UNITY_EDITOR
Object.DestroyImmediate(exportTexture);
#else
Object.Destroy(exportTexture);
#endif
}
return imageData;
#else
return null;
#endif
}
}
}