FM/Assets/Scripts/Runtime/Helper/TextureHelper.cs

399 lines
15 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.IO;
using Cysharp.Threading.Tasks;
using UnityEngine;
namespace ZXL.Helper
{
public static class TextureHelper
{
/// <summary>
/// 精灵图片转纹理
/// </summary>
/// <param name="sprite"></param>
/// <returns></returns>
public static Texture2D SpriteToTexture2D(Sprite sprite)
{
// 获取 Sprite 的纹理
Texture2D texture = sprite.texture;
// 创建一个新的 Texture2D 用于存储 Sprite 的图像数据
Texture2D texture2D = new Texture2D((int)sprite.rect.width, (int)sprite.rect.height);
// 读取 Sprite 的像素数据到新的 Texture2D
Color[] pixels = texture.GetPixels(
(int)sprite.rect.x,
(int)sprite.rect.y,
(int)sprite.rect.width,
(int)sprite.rect.height
);
// 将像素数据设置到新的 Texture2D 中
texture2D.SetPixels(pixels);
texture2D.Apply(); // 应用更改
return texture2D;
}
/// <summary>
/// 纹理转精灵图片
/// </summary>
/// <param name="texture"></param>
/// <returns></returns>
public static Sprite SpriteFromTexture2D(Texture2D texture)
{
Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height),
new Vector2(0.5f, 0.5f));
return sprite;
}
/// <summary>
/// 截取相机画面并返回纹理图片
/// </summary>
/// <param name="camera"></param>
/// <returns></returns>
public static Texture2D SaveCameraToTexture(Camera camera, bool generateMipMaps = false,
TextureFormat textureFormat = TextureFormat.RGBA32)
{
if (camera == null)
{
Debug.LogError("Camera is null!");
return null;
}
RenderTexture originalTargetTexture = camera.targetTexture;
RenderTexture tempRenderTexture = null;
Texture2D capturedImage = null;
try
{
// 创建临时RenderTexture
tempRenderTexture = RenderTexture.GetTemporary(
camera.pixelWidth, camera.pixelHeight, 24, RenderTextureFormat.Default);
// 设置相机渲染到临时RenderTexture
camera.targetTexture = tempRenderTexture;
// 强制相机渲染一帧
camera.Render();
// 创建Texture2D
capturedImage = new Texture2D(
tempRenderTexture.width,
tempRenderTexture.height,
textureFormat,
generateMipMaps);
// 保存当前激活的RenderTexture
RenderTexture previousActive = RenderTexture.active;
// 设置临时RenderTexture为当前激活的以便读取像素
RenderTexture.active = tempRenderTexture;
// 读取像素并应用
capturedImage.ReadPixels(new Rect(0, 0, tempRenderTexture.width, tempRenderTexture.height), 0, 0);
capturedImage.Apply();
// 恢复之前的RenderTexture
RenderTexture.active = previousActive;
}
catch (System.Exception e)
{
Debug.LogError($"Error capturing camera: {e.Message}");
if (capturedImage != null)
{
UnityEngine.Object.DestroyImmediate(capturedImage);
capturedImage = null;
}
}
finally
{
// 恢复相机的原始设置
camera.targetTexture = originalTargetTexture;
// 释放临时RenderTexture
if (tempRenderTexture != null)
{
RenderTexture.ReleaseTemporary(tempRenderTexture);
tempRenderTexture = null;
}
}
return capturedImage;
}
/// <summary>
/// Texture转Texture2D
/// </summary>
/// <param name="texture"></param>
/// <returns></returns>
public static Texture2D ConvertTextureToTexture2D(Texture texture)
{
Texture2D texture2D = new Texture2D(texture.width, texture.height, TextureFormat.RGBA32, false);
RenderTexture currentRT = RenderTexture.active;
// 创建一个新的 RenderTexture
RenderTexture renderTexture = RenderTexture.GetTemporary(texture.width, texture.height, 32);
Graphics.Blit(texture, renderTexture);
// 将 RenderTexture 内容复制到 Texture2D
RenderTexture.active = renderTexture;
texture2D.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
texture2D.Apply();
// 清理
RenderTexture.active = currentRT;
RenderTexture.ReleaseTemporary(renderTexture);
return texture2D;
}
/// <summary>
/// 纹理图片转二进制数据
/// </summary>
/// <param name="texture"></param>
/// <returns></returns>
public static byte[] ConvertTextureToByteArray(Texture2D texture)
{
return texture.EncodeToPNG();
}
/// <summary>
/// 二进制数据转纹理图片
/// </summary>
/// <param name="bytes"></param>
/// <returns></returns>
public static Texture2D ConvertByteArrayToTexture2D(byte[] bytes)
{
Texture2D texture = new Texture2D(2, 2); // 初始化一个临时的 Texture2D
if (texture.LoadImage(bytes)) // 使用 LoadImage 来加载字节数据
{
return texture;
}
else
{
Debug.LogError("加载图片失败!");
return null;
}
}
public static async UniTask TransparentCaptureSystem(TransparentCaptureSystemOption option)
{
/*
if (option.targetCamera == null)
{
throw new NullReferenceException("targetCamera is null");
return;
}
async UniTask CaptureAndCrop()
{
// 确保尺寸有效
ValidateSizes();
// 创建原始截图
await (CaptureOriginalScreenshot());
// 裁剪图片(保留透明通道)
CropWithTransparency();
// 保存结果
SaveCroppedImage();
// 清理资源
CleanupResources();
}
async UniTask CaptureOriginalScreenshot()
{
// 创建RenderTexture带alpha通道
option._renderTexture = new RenderTexture(option.captureWidth, option.captureHeight, 32, RenderTextureFormat.ARGB32);
option._renderTexture.Create();
// 保存原始相机设置
RenderTexture originalRT = option.targetCamera.targetTexture;
CameraClearFlags originalClearFlags = option.targetCamera.clearFlags;
Color originalBackgroundColor = option.targetCamera.backgroundColor;
// 配置相机透明背景
option.targetCamera.targetTexture = option._renderTexture;
option.targetCamera.clearFlags = CameraClearFlags.SolidColor;
option.targetCamera.backgroundColor = option.preserveAlpha ? option.backgroundColor : Color.black;
// 渲染相机
option.targetCamera.Render();
// 创建Texture2D带alpha通道
option._originalTexture = new Texture2D(option.captureWidth, option.captureHeight,
option.preserveAlpha ? TextureFormat.ARGB32 : TextureFormat.RGB24,
false);
// 读取像素包括alpha
RenderTexture.active = option._renderTexture;
option._originalTexture.ReadPixels(new Rect(0, 0, option.captureWidth, option.captureHeight), 0, 0);
option._originalTexture.Apply();
RenderTexture.active = null;
// 恢复相机设置
option.targetCamera.targetTexture = originalRT;
option.targetCamera.clearFlags = originalClearFlags;
option.targetCamera.backgroundColor = originalBackgroundColor;
}
string fullPath;
void CropWithTransparency()
{
if (option._originalTexture == null)
{
Debug.LogError("原始截图未创建!");
return;
}
// 计算裁剪起始位置
int startX = Mathf.FloorToInt((option._originalTexture.width - option.cropWidth) * option.cropOffset.x);
int startY = Mathf.FloorToInt((option._originalTexture.height - option.cropHeight) * option.cropOffset.y);
// 确保在有效范围内
startX = Mathf.Clamp(startX, 0, option._originalTexture.width - option.cropWidth);
startY = Mathf.Clamp(startY, 0, option._originalTexture.height - option.cropHeight);
// 创建裁剪后的纹理带alpha通道
option._croppedTexture = new Texture2D(option.cropWidth, option.cropHeight,
option.preserveAlpha ? TextureFormat.ARGB32 : TextureFormat.RGB24,
false);
// 获取原始纹理的像素数据包括alpha
Color[] pixels = option._originalTexture.GetPixels(startX, startY, option.cropWidth, option.cropHeight);
// 设置到裁剪纹理
option._croppedTexture.SetPixels(pixels);
option._croppedTexture.Apply();
}
void SaveCroppedImage()
{
if (option._croppedTexture == null)
{
Debug.LogError("裁剪后的纹理未创建!");
return;
}
// 创建保存目录
string folderPath = option.saveFolder;
if (!Directory.Exists(folderPath)) Directory.CreateDirectory(folderPath);
// 生成文件名
string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
string extension = option.saveAsPNG ? ".png" : ".jpg";
string fileName;
if (string.IsNullOrEmpty(option.onlyFileName))
fileName = $"{option.fileNamePrefix}_{option.cropWidth}x{option.cropHeight}_{timestamp}{extension}";
else
fileName = $"{option.onlyFileName}{extension}";
fullPath = Path.Combine(folderPath, fileName);
// 编码保存
byte[] imageBytes;
if (option.saveAsPNG)
{
imageBytes = option._croppedTexture.EncodeToPNG();
}
else
{
// JPG不支持透明通道强制去除alpha
Texture2D jpgTexture =
new Texture2D(option._croppedTexture.width, option._croppedTexture.height, TextureFormat.RGB24, false);
jpgTexture.SetPixels(option._croppedTexture.GetPixels());
jpgTexture.Apply();
imageBytes = jpgTexture.EncodeToJPG(90);
}
File.WriteAllBytes(fullPath, imageBytes);
// 验证透明度
if (option.saveAsPNG && option.preserveAlpha)
{
// 检查左上角像素是否透明
Color topLeft = option._croppedTexture.GetPixel(0, option._croppedTexture.height - 1);
Debug.Log($"保存的图片左上角透明度: {topLeft.a}");
// 检查中心像素是否透明
Color center = option._croppedTexture.GetPixel(option._croppedTexture.width / 2, option._croppedTexture.height / 2);
Debug.Log($"保存的图片中心透明度: {center.a}");
}
Debug.Log($"截图已保存至: {fullPath}");
#if UNITY_EDITOR
UnityEditor.EditorUtility.RevealInFinder(fullPath);
#endif
}
void ValidateSizes()
{
// 确保原始尺寸有效
option.captureWidth = Mathf.Clamp(option.captureWidth, 32, SystemInfo.maxTextureSize);
option. captureHeight = Mathf.Clamp(option.captureHeight, 32, SystemInfo.maxTextureSize);
// 确保裁剪尺寸有效
option.cropWidth = Mathf.Clamp(option.cropWidth, 32,option. captureWidth);
option.cropHeight = Mathf.Clamp(option.cropHeight, 32, option.captureHeight);
// 确保偏移量在0-1范围
option.cropOffset.x = Mathf.Clamp01(option.cropOffset.x);
option.cropOffset.y = Mathf.Clamp01(option.cropOffset.y);
}
void CleanupResources()
{
if (option._renderTexture != null)
{
Destroy(_renderTexture);
option._renderTexture = null;
}
if (option._originalTexture != null)
{
Destroy(_originalTexture);
option._originalTexture = null;
}
// 保留裁剪纹理用于预览或后续使用
// 如果不再需要,可以取消注释下面一行
Destroy(_croppedTexture);
}
UniTask.Run(CaptureAndCrop);
*/
}
}
public class TransparentCaptureSystemOption
{
// 相机设置
public Camera targetCamera;
public KeyCode captureKey = KeyCode.C;
// 原始截图设置
public int captureWidth = 1080;
public int captureHeight = 1920;
// 裁剪设置
public int cropWidth = 800;
public int cropHeight = 300;
public Vector2 cropOffset = Vector2.zero; // 裁剪偏移量 (0-1)
// 透明通道
public bool preserveAlpha = true;
public Color backgroundColor = new Color(0, 0, 0, 0); // 透明背景
// 输出设置
public string saveFolder = "Screenshots";
public string fileNamePrefix = "Screenshot";
public bool saveAsPNG = true;
public string onlyFileName = "";
public RenderTexture _renderTexture;
public Texture2D _originalTexture;
public Texture2D _croppedTexture;
}
}