Files

78 lines
3.1 KiB
C#
Raw Permalink Normal View History

using System;
using System.IO;
using System.Windows.Media.Imaging;
namespace PCL.Core.UI.Media;
public static class ImageConverter
{
/// <summary>
/// 从 WebP 输入流解码并转换为 PNG,返回包含 PNG 数据的 MemoryStreamPosition=0)。
/// 需要系统内置的 WebP WIC 编解码器(Windows 10/11 通常已内置或可通过商店扩展提供)。
/// </summary>
/// <param name="input">输入 WebP 流(不会在此方法中关闭)</param>
/// <param name="frameIndex">要提取的帧索引,默认 0</param>
/// <returns>包含 PNG 数据的 MemoryStream,调用方负责释放</returns>
/// <exception cref="ArgumentOutOfRangeException">帧索引超出图像支持范围</exception>
/// <exception cref="NotSupportedException">系统缺少 WebP 解码器,或数据格式不受支持</exception>
// 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();
}
}
}