using UnityEngine; using System.IO; using System.Collections; using System; using Zenith; public class TransparentCaptureSystem : MonoBehaviour { [Header("相机设置")] public Camera targetCamera; public KeyCode captureKey = KeyCode.C; [Header("原始截图设置")] public int captureWidth = 1080; public int captureHeight = 1920; [Header("裁剪设置")] public int cropWidth = 1080; public int cropHeight = 1920; public Vector2 cropOffset = Vector2.zero; // 裁剪偏移量 (0-1) [Header("透明通道")] public bool preserveAlpha = true; public Color backgroundColor = new Color(0, 0, 0, 0); // 透明背景 [Header("输出设置")] public string saveFolder = "Screenshots"; public string fileNamePrefix = "Screenshot"; public bool saveAsPNG = true; public string onlyFileName = ""; private RenderTexture _renderTexture; private Texture2D _originalTexture; private Texture2D _croppedTexture; public Transform uiRoot; public static T Instance; private void Awake() { var allText = File.ReadAllText(Application.streamingAssetsPath + "/picSavePath.txt"); if (string.IsNullOrEmpty(allText)) { #if !UNITY_EDITOR saveFolder = Path.Combine(Application.dataPath, "Screenshots"); #endif } else { saveFolder = allText; } Init(); } void Start() { if (targetCamera == null) targetCamera = Camera.main; } protected virtual void Init() { } public IEnumerator CaptureAndCrop(Action callback = null) { // 确保尺寸有效 ValidateSizes(); // 创建原始截图 yield return StartCoroutine(CaptureOriginalScreenshot()); // 裁剪图片(保留透明通道) CropWithTransparency(); // 保存结果 SaveCroppedImage(); // 清理资源 CleanupResources(); callback?.Invoke(bytes); } // 【核心修改】优化截图渲染流程,避免RT显示在屏幕上 private IEnumerator CaptureOriginalScreenshot() { // 1. 保存相机原始状态(增加关键状态保存) RenderTexture originalRT = targetCamera.targetTexture; CameraClearFlags originalClearFlags = targetCamera.clearFlags; Color originalBackgroundColor = targetCamera.backgroundColor; bool originalEnabled = targetCamera.enabled; // 保存相机启用状态 // bool originalRenderInEditMode = targetCamera.renderInEditMode; // 编辑模式渲染状态 // 2. 创建临时RenderTexture _renderTexture = RenderTexture.GetTemporary( captureWidth, captureHeight, 32, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear ); try { // 3. 配置相机仅渲染到RT,不显示在屏幕 targetCamera.enabled = false; // 禁用相机的自动渲染 // targetCamera.renderInEditMode = true; // 允许编辑模式渲染 targetCamera.targetTexture = _renderTexture; targetCamera.clearFlags = CameraClearFlags.SolidColor; targetCamera.backgroundColor = preserveAlpha ? backgroundColor : Color.black; // 4. 手动渲染相机到RT(此操作不会显示在屏幕) targetCamera.Render(); // 5. 读取RT像素到Texture2D RenderTexture.active = _renderTexture; _originalTexture = new Texture2D(captureWidth, captureHeight, preserveAlpha ? TextureFormat.ARGB32 : TextureFormat.RGB24, false); _originalTexture.ReadPixels(new Rect(0, 0, captureWidth, captureHeight), 0, 0); _originalTexture.Apply(); } finally { // 6. 无论是否出错,都强制恢复相机设置 targetCamera.targetTexture = originalRT; targetCamera.clearFlags = originalClearFlags; targetCamera.backgroundColor = originalBackgroundColor; targetCamera.enabled = originalEnabled; // targetCamera.renderInEditMode = originalRenderInEditMode; RenderTexture.active = null; // 强制取消RT激活状态 } yield return null; } private IEnumerator CaptureOriginalScreenshot1() { // 创建RenderTexture(带alpha通道) _renderTexture = new RenderTexture(captureWidth, captureHeight, 32, RenderTextureFormat.ARGB32); _renderTexture.Create(); // 保存原始相机设置 RenderTexture originalRT = targetCamera.targetTexture; CameraClearFlags originalClearFlags = targetCamera.clearFlags; Color originalBackgroundColor = targetCamera.backgroundColor; // 配置相机透明背景 targetCamera.targetTexture = _renderTexture; targetCamera.clearFlags = CameraClearFlags.SolidColor; targetCamera.backgroundColor = preserveAlpha ? backgroundColor : Color.black; // 渲染相机 targetCamera.Render(); // 创建Texture2D(带alpha通道) _originalTexture = new Texture2D(captureWidth, captureHeight, preserveAlpha ? TextureFormat.ARGB32 : TextureFormat.RGB24, false); // 读取像素(包括alpha) RenderTexture.active = _renderTexture; _originalTexture.ReadPixels(new Rect(0, 0, captureWidth, captureHeight), 0, 0); _originalTexture.Apply(); RenderTexture.active = null; // 恢复相机设置 targetCamera.targetTexture = originalRT; targetCamera.clearFlags = originalClearFlags; targetCamera.backgroundColor = originalBackgroundColor; yield return null; } string fullPath; public string FullPath => fullPath; private void CropWithTransparency() { if (_originalTexture == null) { Debug.LogError("原始截图未创建!"); return; } // 计算裁剪起始位置 int startX = Mathf.FloorToInt((_originalTexture.width - cropWidth) * cropOffset.x); int startY = Mathf.FloorToInt((_originalTexture.height - cropHeight) * cropOffset.y); // 确保在有效范围内 startX = Mathf.Clamp(startX, 0, _originalTexture.width - cropWidth); startY = Mathf.Clamp(startY, 0, _originalTexture.height - cropHeight); // 创建裁剪后的纹理(带alpha通道) _croppedTexture = new Texture2D(cropWidth, cropHeight, preserveAlpha ? TextureFormat.ARGB32 : TextureFormat.RGB24, false); // 获取原始纹理的像素数据(包括alpha) Color[] pixels = _originalTexture.GetPixels(startX, startY, cropWidth, cropHeight); // 设置到裁剪纹理 _croppedTexture.SetPixels(pixels); _croppedTexture.Apply(); } // public static void SaveImage(Texture2D tex, string name) // { // byte[] bytes = tex.EncodeToPNG(); // var dirPath = "SaveImages/"; // if (!Directory.Exists(dirPath)) // { // Directory.CreateDirectory(dirPath); // } // File.WriteAllBytes(dirPath + name + ".png", B83.Image.PNGTools.ChangePPI(bytes, 300, 300)); // } private void SaveCroppedImage() { if (_croppedTexture == null) { Debug.LogError("裁剪后的纹理未创建!"); return; } // 创建保存目录 string folderPath = saveFolder; if (!Directory.Exists(folderPath)) Directory.CreateDirectory(folderPath); // 生成文件名 string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss"); string extension = saveAsPNG ? ".png" : ".jpg"; string fileName; string dpiName; if (string.IsNullOrEmpty(onlyFileName)) fileName = $"{fileNamePrefix}_{cropWidth}x{cropHeight}_{timestamp}{extension}"; else fileName = $"{onlyFileName}{extension}"; dpiName = $"{fileNamePrefix}_{cropWidth}x{cropHeight}_{timestamp}_DPI_{extension}"; fullPath = Path.Combine(folderPath, fileName); var dpiFullPath = Path.Combine(folderPath, dpiName); // 编码保存 byte[] imageBytes; if (saveAsPNG) { imageBytes = _croppedTexture.EncodeToPNG(); } else { // JPG不支持透明通道,强制去除alpha Texture2D jpgTexture = new Texture2D(_croppedTexture.width, _croppedTexture.height, TextureFormat.RGB24, false); jpgTexture.SetPixels(_croppedTexture.GetPixels()); jpgTexture.Apply(); imageBytes = jpgTexture.EncodeToJPG(90); Destroy(jpgTexture); } // File.WriteAllBytes(fullPath, imageBytes); ImageDpiProcessor.SaveTextureWithDpi(_croppedTexture, fullPath, 300); Debug.Log($"save as: {fullPath}"); // 验证透明度 if (saveAsPNG && preserveAlpha) { // 检查左上角像素是否透明 Color topLeft = _croppedTexture.GetPixel(0, _croppedTexture.height - 1); Debug.Log($"保存的图片左上角透明度: {topLeft.a}"); // 检查中心像素是否透明 Color center = _croppedTexture.GetPixel(_croppedTexture.width / 2, _croppedTexture.height / 2); Debug.Log($"保存的图片中心透明度: {center.a}"); } Debug.Log($"截图已保存至: {fullPath}"); bytes = File.ReadAllBytes(fullPath); // NetworkUpload.instance.miniCooperData.items[0].preview1 = System.Convert.ToBase64String(bytes); #if UNITY_EDITOR UnityEditor.EditorUtility.RevealInFinder(fullPath); #endif } byte[] bytes; private void ValidateSizes() { // 确保原始尺寸有效 captureWidth = Mathf.Clamp(captureWidth, 32, SystemInfo.maxTextureSize); captureHeight = Mathf.Clamp(captureHeight, 32, SystemInfo.maxTextureSize); // 确保裁剪尺寸有效 cropWidth = Mathf.Clamp(cropWidth, 32, captureWidth); cropHeight = Mathf.Clamp(cropHeight, 32, captureHeight); // 确保偏移量在0-1范围 cropOffset.x = Mathf.Clamp01(cropOffset.x); cropOffset.y = Mathf.Clamp01(cropOffset.y); } private void CleanupResources() { if (_renderTexture != null) { Destroy(_renderTexture); _renderTexture = null; } if (_originalTexture != null) { Destroy(_originalTexture); _originalTexture = null; } // 保留裁剪纹理用于预览或后续使用 // 如果不再需要,可以取消注释下面一行 Destroy(_croppedTexture); } [ContextMenu("立即截图并裁剪")] public virtual void CaptureAndCropNow(Action callback = null) { StartCoroutine(CaptureAndCrop(callback)); } void OnGUI() { // 显示原始截图预览 if (_originalTexture != null) { GUI.DrawTexture(new Rect(10, 10, 200, 200 * (float)captureHeight / captureWidth), _originalTexture, ScaleMode.ScaleToFit); GUI.Label(new Rect(10, 220, 200, 30), $"原始尺寸: {captureWidth}x{captureHeight}"); } // 显示裁剪后截图预览 if (_croppedTexture != null) { GUI.DrawTexture(new Rect(Screen.width - 210, 10, 200, 200 * (float)cropHeight / cropWidth), _croppedTexture, ScaleMode.ScaleToFit); GUI.Label(new Rect(Screen.width - 210, 220, 200, 30), $"裁剪尺寸: {cropWidth}x{cropHeight}"); // 显示透明度信息 if (preserveAlpha) { GUI.Label(new Rect(Screen.width - 210, 250, 200, 30), "包含透明通道"); } } } void OnDestroy() { CleanupResources(); if (_croppedTexture != null) { Destroy(_croppedTexture); _croppedTexture = null; } } }