using SpineViewer.Spine; using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing.Imaging; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SpineViewer.Spine.SpineExporter { /// /// 单帧画面导出器 /// public class FrameExporter : Exporter { /// /// 单帧画面格式 /// public ImageFormat ImageFormat { get => imageFormat; set { if (value == ImageFormat.MemoryBmp) value = ImageFormat.Bmp; imageFormat = value; } } private ImageFormat imageFormat = ImageFormat.Png; /// /// DPI /// public SizeF DPI { get => dpi; set { if (value.Width <= 0) value.Width = 144; if (value.Height <= 0) value.Height = 144; dpi = value; } } private SizeF dpi = new(144, 144); protected override void ExportSingle(SpineObject[] spinesToRender, BackgroundWorker? worker = null) { // 导出单个时必定提供输出文件夹 var filename = $"frame_{timestamp}{ImageFormat.GetSuffix()}"; var savePath = Path.Combine(OutputDir, filename); worker?.ReportProgress(0, $"已处理 0/1"); try { using var frame = GetFrame(spinesToRender); using var img = frame.CopyToBitmap(); img.SetResolution(DPI.Width, DPI.Height); img.Save(savePath, ImageFormat); } catch (Exception ex) { logger.Error(ex.ToString()); logger.Error("Failed to save single frame"); } worker?.ReportProgress(100, $"已处理 1/1"); } protected override void ExportIndividual(SpineObject[] spinesToRender, BackgroundWorker? worker = null) { int total = spinesToRender.Length; int success = 0; int error = 0; worker?.ReportProgress(0, $"已处理 0/{total}"); for (int i = 0; i < total; i++) { var spine = spinesToRender[i]; // 逐个导出时如果提供了输出文件夹, 则全部导出到输出文件夹, 否则输出到各自的文件夹 var filename = $"{spine.Name}_{timestamp}{ImageFormat.GetSuffix()}"; var savePath = Path.Combine(OutputDir ?? spine.AssetsDir, filename); try { using var frame = GetFrame(spine); using var img = frame.CopyToBitmap(); img.SetResolution(DPI.Width, DPI.Height); img.Save(savePath, ImageFormat); success++; } catch (Exception ex) { logger.Error(ex.ToString()); logger.Error("Failed to save single frame {} {}", savePath, spine.SkelPath); error++; } worker?.ReportProgress((int)((i + 1) * 100.0) / total, $"已处理 {i + 1}/{total}"); } if (error > 0) logger.Warn("Frames save {} successfully, {} failed", success, error); else logger.Info("{} frames saved successfully", success); } } public class FrameExporterProperty(FrameExporter exporter) : ExporterProperty(exporter) { [Browsable(false)] public override FrameExporter Exporter => (FrameExporter)base.Exporter; /// /// 单帧画面格式 /// [TypeConverter(typeof(ImageFormatConverter))] [Category("[1] 单帧画面"), DisplayName("图像格式")] public ImageFormat ImageFormat { get => Exporter.ImageFormat; set => Exporter.ImageFormat = value; } /// /// 文件名后缀 /// [Category("[1] 单帧画面"), DisplayName("文件名后缀"), Description("与图像格式匹配的文件名后缀")] public string Suffix { get => Exporter.ImageFormat.GetSuffix(); } /// /// DPI /// [TypeConverter(typeof(SizeFConverter))] [Category("[1] 单帧画面"), DisplayName("DPI"), Description("导出图像的每英寸像素数,用于调整图像的物理尺寸")] public SizeF DPI { get => Exporter.DPI; set => Exporter.DPI = value; } } }