using System; using System.IO; using System.Windows.Media.Imaging; namespace PCL.Core.UI.Media; public static class ImageConverter { /// /// 从 WebP 输入流解码并转换为 PNG,返回包含 PNG 数据的 MemoryStream(Position=0)。 /// 需要系统内置的 WebP WIC 编解码器(Windows 10/11 通常已内置或可通过商店扩展提供)。 /// /// 输入 WebP 流(不会在此方法中关闭) /// 要提取的帧索引,默认 0 /// 包含 PNG 数据的 MemoryStream,调用方负责释放 /// 帧索引超出图像支持范围 /// 系统缺少 WebP 解码器,或数据格式不受支持 // Partly generated by gpt-5 (20250813) public static MemoryStream FromWebpToPng(this Stream input, int frameIndex = 0) { // 确保有可寻址的源流 var source = input; MemoryStream? tempBuffer = null; if (!input.CanSeek) { tempBuffer = new MemoryStream(); input.CopyTo(tempBuffer); tempBuffer.Position = 0; source = tempBuffer; } else { // 从开头解码 if (source.Position != 0) source.Position = 0; } try { // 使用 WPF 的 BitmapDecoder(底层是 WIC)。OnLoad 使得图像数据在解码完成后与源流解耦。 var decoder = BitmapDecoder.Create( source, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad); if (decoder.Frames.Count == 0) throw new NotSupportedException("未能从输入数据解码出任何图像帧,可能不是有效的 WebP 图像。"); if (frameIndex < 0 || frameIndex >= decoder.Frames.Count) throw new ArgumentOutOfRangeException(nameof(frameIndex), $"帧索引超出范围(0..{decoder.Frames.Count - 1})。"); var frame = decoder.Frames[frameIndex]; var encoder = new PngBitmapEncoder(); // 使用 BitmapFrame.Create 包装,避免后续冻结或依赖源的问题 encoder.Frames.Add(BitmapFrame.Create(frame)); var output = new MemoryStream(); encoder.Save(output); output.Position = 0; return output; } catch (NotSupportedException) { // 透传,提示缺少编解码器或格式不支持 throw; } catch (Exception ex) { // 统一转为更明确的异常信息(保留原始异常以便调试) throw new NotSupportedException("转换 WebP 到 PNG 失败:输入可能不是有效的 WebP,或系统未提供所需的编解码支持。", ex); } finally { // 仅释放我们创建的临时缓冲,不关闭调用方传入的 input tempBuffer?.Dispose(); } } }