using UnityEngine; using System; using System.Collections; using System.Collections.Generic; using System.IO; using UnityEngine.UI; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.Processing; namespace HK.FUJIFILM { public class DoubleCaptureSystem : TransparentCaptureSystem { /// /// 执行两次截图并裁剪,支持分别定制参数 /// /// 两次都完成后的回调(返回两次的字节数组) public void CaptureTwice(Action onBothComplete) { StartCoroutine(CoCaptureTwice(onBothComplete)); } /// /// 一开多 /// /// public void CaptureTwice_ManyToMany(Action, List> onBothComplete) { StartCoroutine(CoCaptureTwice_ManyToMany(onBothComplete)); } public void CaptureTwice_OneToMany(Action> onBothComplete) { StartCoroutine(CoCaptureTwice_OneToMany(onBothComplete)); } public void CaptureOnlyDesign(Action onBothComplete) { StartCoroutine(CoCaptureOnlyDesign(onBothComplete)); } #if UNITY_EDITOR [ContextMenu("CaptureTwice")] public void Test() { StartCoroutine(CoCaptureTwice(null)); } #endif float ConvertMmToPixel(float mm, int dpi = 300) { return mm * (dpi / 25.4f); } // private void Update() // { // if (Input.GetKeyDown(KeyCode.J)) // { // UnityEngine.Debug.LogError($"px is {ConvertMmToPixel(85.6f)}"); // } // } // 协程:顺序执行两次截图 private IEnumerator CoCaptureTwice(Action onBothComplete) { // 存储两次截图的结果 byte[] firstResult = null; byte[] secondResult = null; var tmpSaveFolder = saveFolder; saveFolder = Path.Combine(saveFolder, DateTime.Now.ToString("yyyyMMdd_HHmmss")); onlyFileName = "PreviewImage1"; var mugActualModelRenderFixed = uiRoot.GetComponent(); var image = mugActualModelRenderFixed.designParent.GetChild(0).GetComponent(); image.enabled = true; // 第一次截图(使用基类默认参数) Debug.Log("开始第一次截图..."); yield return StartCoroutine(CaptureAndCrop((firstBytes) => { firstResult = firstBytes; Debug.Log("第一次截图完成"); })); image.enabled = false; // 确保第一次完成后再执行第二次 if (firstResult == null) { Debug.LogError("第一次截图失败,取消第二次"); onBothComplete?.Invoke(null, null); yield break; } bool tmpImageActive = image.enabled; image.enabled = mugActualModelRenderFixed.productScriptableObject.isShowTemplate; var verticalLayoutGroup = mugActualModelRenderFixed.designParent.GetComponent(); verticalLayoutGroup.enabled = true; var tmpWidth = cropWidth; var tmpHeight = cropHeight; var productScriptableObject = mugActualModelRenderFixed.productScriptableObject; var screenshotSize = productScriptableObject.screenshotSize; cropWidth = (int)screenshotSize.x; cropHeight = (int)screenshotSize.y; cropOffset = new Vector2(0.5f, 0.5f); onlyFileName = "DesignImage1"; // 第二次截图(使用修改后的参数) Debug.Log("开始第二次截图..."); yield return StartCoroutine(CaptureAndCrop((secondBytes) => { secondResult = secondBytes; Debug.Log("第二次截图完成"); })); image.enabled = tmpImageActive; // 1. 校验文件是否存在 var fileInfo = new FileInfo(fullPath); if (!fileInfo.Exists) { Debug.LogError($"原始图片不存在:{fullPath}"); secondResult = null; yield break; // 若在协程中,用 yield break 退出 } try { // 2. 加载图像并校验原始尺寸 using (var sImage = SixLabors.ImageSharp.Image.Load(fileInfo.FullName)) { // 校验原始图片尺寸是否有效 if (sImage.Width <= 0 || sImage.Height <= 0) { Debug.LogError($"加载的图片尺寸无效:宽={sImage.Width}, 高={sImage.Height}"); secondResult = null; yield break; } if (productScriptableObject.printingSize.x != 0) { // 3. 校验缩放宽度是否有效 int targetWidth = (int)ConvertMmToPixel(productScriptableObject.printingSize.x); int targetHeight = (int)ConvertMmToPixel(productScriptableObject.printingSize.y); if (targetWidth <= 0) { Debug.LogError($"缩放宽度无效(必须大于 0):{targetWidth}"); // 可选:使用默认宽度(如 200)避免错误 targetWidth = 200; } // 4. 等比缩放(确保目标尺寸有效) // sImage.Mutate(x => x.Resize(new ResizeOptions // { // Size = new Size(targetWidth, targetHeight), // 高度为0则自动计算 // Mode = ResizeMode.Max, // Sampler = KnownResamplers.Lanczos3 // 高质量缩放算法 // })); // 强制缩放 sImage.Mutate(x => x.Resize(targetWidth, targetHeight)); } // 5. 确保保存目录存在 if (!Directory.Exists(saveFolder)) { Directory.CreateDirectory(saveFolder); // 自动创建目录 } // 6. 保存缩放后的图片 var filePath = Path.Combine(saveFolder, "Printing1.png"); sImage.SaveAsPng(filePath, new PngEncoder()); // 7. 校验保存结果并读取字节数组 if (File.Exists(filePath)) { secondResult = File.ReadAllBytes(filePath); Debug.Log($"第二次截图缩放后保存至:{filePath}"); } else { Debug.LogError($"图片保存失败,文件不存在:{filePath}"); secondResult = null; } } } catch (Exception ex) { // 捕获所有异常(如图片格式错误、权限问题等) Debug.LogError($"图片处理失败:{ex.Message}\n{ex.StackTrace}"); secondResult = null; } // 恢复原始参数(避免影响后续截图) verticalLayoutGroup.enabled = false; cropWidth = tmpWidth; cropHeight = tmpHeight; cropOffset = new Vector2(0f, 0f); image.enabled = false; saveFolder = tmpSaveFolder; // 触发最终回调 onBothComplete?.Invoke(firstResult, secondResult); } private IEnumerator CoCaptureTwice_OneToMany(Action> onBothComplete) { byte[] firstResult = null; List secondResults = new List(); var tmpSaveFolder = saveFolder; var mugActualModelRenderFixed = uiRoot.GetComponent(); saveFolder = Path.Combine(saveFolder, DateTime.Now.ToString("yyyyMMdd_HHmmss")); var designParent = mugActualModelRenderFixed.designParent.GetChild(0); onlyFileName = $"PreviewImage"; var tmpImageEnabled = false; for (var i = 0; i < designParent.childCount; i++) { var image = designParent.GetChild(i).GetComponent(); tmpImageEnabled = image.enabled; image.enabled = mugActualModelRenderFixed.productScriptableObject.isShowBaseMap; } // 第一次截图(使用基类默认参数) Debug.Log("开始第一次截图..."); yield return StartCoroutine(CaptureAndCrop((firstBytes) => { firstResult = firstBytes; Debug.Log("第一次截图完成"); })); for (var i = 0; i < designParent.childCount; i++) { var image = designParent.GetChild(i).GetComponent(); image.enabled = tmpImageEnabled; } // 确保第一次完成后再执行第二次 if (firstResult == null) { Debug.LogError("第一次截图失败,取消第二次"); onBothComplete?.Invoke(null, null); yield break; } for (var i = 0; i < designParent.childCount; i++) { // 存储两次截图的结果 byte[] secondResult = null; for (var j = 0; j < designParent.childCount; j++) { designParent.GetChild(j).gameObject.SetActive(false); } designParent.GetChild(i).gameObject.SetActive(true); var verticalLayoutGroup = designParent.GetComponent(); if (verticalLayoutGroup != null) verticalLayoutGroup.enabled = true; var tmpWidth = cropWidth; var tmpHeight = cropHeight; var productScriptableObject = mugActualModelRenderFixed.productScriptableObject; var screenshotSize = productScriptableObject.screenshotSize; cropWidth = (int)screenshotSize.x; cropHeight = (int)screenshotSize.y; cropOffset = new Vector2(0.5f, 0.5f); onlyFileName = $"DesignImage{i}"; // 第二次截图(使用修改后的参数) Debug.Log("开始第二次截图..."); yield return StartCoroutine(CaptureAndCrop((secondBytes) => { secondResult = secondBytes; Debug.Log("第二次截图完成"); })); // image.enabled = tmpImageActive; // 1. 校验文件是否存在 var fileInfo = new FileInfo(fullPath); if (!fileInfo.Exists) { Debug.LogError($"原始图片不存在:{fullPath}"); secondResult = null; yield break; // 若在协程中,用 yield break 退出 } try { // 2. 加载图像并校验原始尺寸 using (var sImage = SixLabors.ImageSharp.Image.Load(fileInfo.FullName)) { // 校验原始图片尺寸是否有效 if (sImage.Width <= 0 || sImage.Height <= 0) { Debug.LogError($"加载的图片尺寸无效:宽={sImage.Width}, 高={sImage.Height}"); secondResult = null; yield break; } if (productScriptableObject.printingSize.x != 0) { // 3. 校验缩放宽度是否有效 int targetWidth = (int)ConvertMmToPixel(productScriptableObject.printingSize.x); int targetHeight = (int)ConvertMmToPixel(productScriptableObject.printingSize.y); if (targetWidth <= 0) { Debug.LogError($"缩放宽度无效(必须大于 0):{targetWidth}"); // 可选:使用默认宽度(如 200)避免错误 targetWidth = 200; } // 4. 等比缩放(确保目标尺寸有效) // sImage.Mutate(x => x.Resize(new ResizeOptions // { // Size = new Size(targetWidth, targetHeight), // 高度为0则自动计算 // Mode = ResizeMode.Max, // Sampler = KnownResamplers.Lanczos3 // 高质量缩放算法 // })); // 强制缩放 sImage.Mutate(x => x.Resize(targetWidth, targetHeight)); } // 5. 确保保存目录存在 if (!Directory.Exists(saveFolder)) { Directory.CreateDirectory(saveFolder); // 自动创建目录 } // 6. 保存缩放后的图片 var filePath = Path.Combine(saveFolder, $"Printing{i}.png"); sImage.SaveAsPng(filePath, new PngEncoder()); // 7. 校验保存结果并读取字节数组 if (File.Exists(filePath)) { secondResult = File.ReadAllBytes(filePath); Debug.Log($"第二次截图缩放后保存至:{filePath}"); } else { Debug.LogError($"图片保存失败,文件不存在:{filePath}"); secondResult = null; } } } catch (Exception ex) { // 捕获所有异常(如图片格式错误、权限问题等) Debug.LogError($"图片处理失败:{ex.Message}\n{ex.StackTrace}"); secondResult = null; } // 恢复原始参数(避免影响后续截图) if (verticalLayoutGroup != null) verticalLayoutGroup.enabled = false; cropWidth = tmpWidth; cropHeight = tmpHeight; cropOffset = new Vector2(0f, 0f); // image.enabled = false; secondResults.Add(secondResult); } for (var j = 0; j < designParent.childCount; j++) { designParent.GetChild(j).gameObject.SetActive(true); } saveFolder = tmpSaveFolder; // 触发最终回调 onBothComplete?.Invoke(firstResult, secondResults); } private IEnumerator CoCaptureTwice_ManyToMany(Action, List> onBothComplete) { List firstResults = new List(); List secondResults = new List(); var tmpSaveFolder = saveFolder; var mugActualModelRenderFixed = uiRoot.GetComponent(); saveFolder = Path.Combine(saveFolder, DateTime.Now.ToString("yyyyMMdd_HHmmss")); var designParent = mugActualModelRenderFixed.designParent.GetChild(0); for (var i = 0; i < designParent.childCount; i++) { // 存储两次截图的结果 byte[] firstResult = null; byte[] secondResult = null; onlyFileName = $"PreviewImage{i}"; var image = designParent.GetChild(i).GetComponent(); image.enabled = true; // 第一次截图(使用基类默认参数) Debug.Log("开始第一次截图..."); yield return StartCoroutine(CaptureAndCrop((firstBytes) => { firstResult = firstBytes; Debug.Log("第一次截图完成"); })); image.enabled = false; // 确保第一次完成后再执行第二次 if (firstResult == null) { Debug.LogError("第一次截图失败,取消第二次"); onBothComplete?.Invoke(null, null); yield break; } bool tmpImageActive = image.enabled; image.enabled = mugActualModelRenderFixed.productScriptableObject.isShowTemplate; var verticalLayoutGroup = designParent.GetComponent(); verticalLayoutGroup.enabled = true; var tmpWidth = cropWidth; var tmpHeight = cropHeight; var productScriptableObject = mugActualModelRenderFixed.productScriptableObject; var screenshotSize = productScriptableObject.screenshotSize; cropWidth = (int)screenshotSize.x; cropHeight = (int)screenshotSize.y; cropOffset = new Vector2(0.5f, 0.5f); onlyFileName = $"DesignImage{i}"; // 第二次截图(使用修改后的参数) Debug.Log("开始第二次截图..."); yield return StartCoroutine(CaptureAndCrop((secondBytes) => { secondResult = secondBytes; Debug.Log("第二次截图完成"); })); image.enabled = tmpImageActive; // 1. 校验文件是否存在 var fileInfo = new FileInfo(fullPath); if (!fileInfo.Exists) { Debug.LogError($"原始图片不存在:{fullPath}"); secondResult = null; yield break; // 若在协程中,用 yield break 退出 } try { // 2. 加载图像并校验原始尺寸 using (var sImage = SixLabors.ImageSharp.Image.Load(fileInfo.FullName)) { // 校验原始图片尺寸是否有效 if (sImage.Width <= 0 || sImage.Height <= 0) { Debug.LogError($"加载的图片尺寸无效:宽={sImage.Width}, 高={sImage.Height}"); secondResult = null; yield break; } if (productScriptableObject.printingSize.x != 0) { // 3. 校验缩放宽度是否有效 int targetWidth = (int)ConvertMmToPixel(productScriptableObject.printingSize.x); int targetHeight = (int)ConvertMmToPixel(productScriptableObject.printingSize.y); if (targetWidth <= 0) { Debug.LogError($"缩放宽度无效(必须大于 0):{targetWidth}"); // 可选:使用默认宽度(如 200)避免错误 targetWidth = 200; } // 4. 等比缩放(确保目标尺寸有效) // sImage.Mutate(x => x.Resize(new ResizeOptions // { // Size = new Size(targetWidth, targetHeight), // 高度为0则自动计算 // Mode = ResizeMode.Max, // Sampler = KnownResamplers.Lanczos3 // 高质量缩放算法 // })); // 强制缩放 sImage.Mutate(x => x.Resize(targetWidth, targetHeight)); } // 5. 确保保存目录存在 if (!Directory.Exists(saveFolder)) { Directory.CreateDirectory(saveFolder); // 自动创建目录 } // 6. 保存缩放后的图片 var filePath = Path.Combine(saveFolder, $"Printing{i}.png"); sImage.SaveAsPng(filePath, new PngEncoder()); // 7. 校验保存结果并读取字节数组 if (File.Exists(filePath)) { secondResult = File.ReadAllBytes(filePath); Debug.Log($"第二次截图缩放后保存至:{filePath}"); } else { Debug.LogError($"图片保存失败,文件不存在:{filePath}"); secondResult = null; } } } catch (Exception ex) { // 捕获所有异常(如图片格式错误、权限问题等) Debug.LogError($"图片处理失败:{ex.Message}\n{ex.StackTrace}"); secondResult = null; } // 恢复原始参数(避免影响后续截图) verticalLayoutGroup.enabled = false; cropWidth = tmpWidth; cropHeight = tmpHeight; cropOffset = new Vector2(0f, 0f); image.enabled = false; firstResults.Add(firstResult); secondResults.Add(secondResult); } saveFolder = tmpSaveFolder; // 触发最终回调 onBothComplete?.Invoke(firstResults, secondResults); } // 协程:顺序执行一次设计截图 private IEnumerator CoCaptureOnlyDesign(Action onBothComplete) { // 存储两次截图的结果 byte[] secondResult = null; string tmpFolder = ""; var tmpSaveFolder = saveFolder; saveFolder = Path.Combine(saveFolder, DateTime.Now.ToString("yyyyMMdd_HHmmss")); tmpFolder = saveFolder; var mugActualModelRenderFixed = uiRoot.GetComponent(); var image = mugActualModelRenderFixed.designParent.GetChild(0).GetComponent(); bool tmpImageActive = image.enabled; image.enabled = mugActualModelRenderFixed.productScriptableObject.isShowTemplate; var verticalLayoutGroup = mugActualModelRenderFixed.designParent.GetComponent(); verticalLayoutGroup.enabled = true; var tmpWidth = cropWidth; var tmpHeight = cropHeight; var productScriptableObject = mugActualModelRenderFixed.productScriptableObject; var screenshotSize = productScriptableObject.screenshotSize; cropWidth = (int)screenshotSize.x; cropHeight = (int)screenshotSize.y; cropOffset = new Vector2(0.5f, 0.5f); onlyFileName = "DesignImage1"; // 第二次截图(使用修改后的参数) Debug.Log("开始第二次截图..."); yield return StartCoroutine(CaptureAndCrop((secondBytes) => { secondResult = secondBytes; Debug.Log("第二次截图完成"); })); image.enabled = tmpImageActive; // 1. 校验文件是否存在 var fileInfo = new FileInfo(fullPath); if (!fileInfo.Exists) { Debug.LogError($"原始图片不存在:{fullPath}"); secondResult = null; yield break; // 若在协程中,用 yield break 退出 } try { // 2. 加载图像并校验原始尺寸 using (var sImage = SixLabors.ImageSharp.Image.Load(fileInfo.FullName)) { // 校验原始图片尺寸是否有效 if (sImage.Width <= 0 || sImage.Height <= 0) { Debug.LogError($"加载的图片尺寸无效:宽={sImage.Width}, 高={sImage.Height}"); secondResult = null; yield break; } if (productScriptableObject.printingSize.x != 0) { // 3. 校验缩放宽度是否有效 int targetWidth = (int)ConvertMmToPixel(productScriptableObject.printingSize.x); int targetHeight = (int)ConvertMmToPixel(productScriptableObject.printingSize.y); if (targetWidth <= 0) { Debug.LogError($"缩放宽度无效(必须大于 0):{targetWidth}"); // 可选:使用默认宽度(如 200)避免错误 targetWidth = 200; } // 4. 等比缩放(确保目标尺寸有效) // sImage.Mutate(x => x.Resize(new ResizeOptions // { // Size = new Size(targetWidth, targetHeight), // 高度为0则自动计算 // Mode = ResizeMode.Max, // Sampler = KnownResamplers.Lanczos3 // 高质量缩放算法 // })); // 强制缩放 sImage.Mutate(x => x.Resize(targetWidth, targetHeight)); } // 5. 确保保存目录存在 if (!Directory.Exists(saveFolder)) { Directory.CreateDirectory(saveFolder); // 自动创建目录 } // 6. 保存缩放后的图片 var filePath = Path.Combine(saveFolder, "Printing1.png"); sImage.SaveAsPng(filePath, new PngEncoder()); // 7. 校验保存结果并读取字节数组 if (File.Exists(filePath)) { secondResult = File.ReadAllBytes(filePath); Debug.Log($"第二次截图缩放后保存至:{filePath}"); } else { Debug.LogError($"图片保存失败,文件不存在:{filePath}"); secondResult = null; } } } catch (Exception ex) { // 捕获所有异常(如图片格式错误、权限问题等) Debug.LogError($"图片处理失败:{ex.Message}\n{ex.StackTrace}"); secondResult = null; } // 恢复原始参数(避免影响后续截图) verticalLayoutGroup.enabled = false; cropWidth = tmpWidth; cropHeight = tmpHeight; cropOffset = new Vector2(0f, 0f); image.enabled = false; saveFolder = tmpSaveFolder; // 触发最终回调 onBothComplete?.Invoke(secondResult, tmpFolder); } // 可选:重写基类的立即截图方法,使其默认执行两次 // public override void CaptureAndCropNow(Action callback = null) // { // base.CaptureAndCropNow(callback); // // // 如果需要点击按钮时默认执行两次,可在这里调用CaptureTwice // // CaptureTwice((first, second) => // // { // // callback?.Invoke(first); // 这里仅返回第一次的结果,或按需处理 // // }); // } } }