using System;
using System.Runtime.InteropServices;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Emgu.CV;
using Emgu.CV.CvEnum;
namespace XP.Common.Converters
{
///
/// 图像数据转换工具类,基于 Emgu CV 实现
///
public static class ImageConverter
{
///
/// 将 16 位无符号灰度数据转换为 RGB BitmapSource
/// 使用 Emgu CV 的 Normalize 进行线性拉伸,CvtColor 转 BGR
///
/// 16 位灰度原始数据
/// 图像宽度
/// 图像高度
/// BGR24 格式的 BitmapSource
public static BitmapSource ConvertGray16ToBitmapSource(ushort[] data, int width, int height)
{
if (data == null) throw new ArgumentNullException(nameof(data));
if (width <= 0 || height <= 0) throw new ArgumentException("图像尺寸无效");
// 从 ushort[] 按字节拷贝构建 16 位灰度 Mat
using var mat16 = new Mat(height, width, DepthType.Cv16U, 1);
int byteCount = data.Length * sizeof(ushort);
unsafe
{
fixed (ushort* pData = data)
{
Buffer.MemoryCopy(pData, mat16.DataPointer.ToPointer(), byteCount, byteCount);
}
}
// 归一化到 0~255 并转为 8 位
using var mat8 = new Mat();
CvInvoke.Normalize(mat16, mat8, 0, 255, NormType.MinMax, DepthType.Cv8U);
// 灰度转 BGR(立式 CT 显示需要 RGB 格式)
using var matBgr = new Mat();
CvInvoke.CvtColor(mat8, matBgr, ColorConversion.Gray2Bgr);
// Mat 转 BitmapSource
return MatToBitmapSource(matBgr);
}
///
/// 将 Emgu CV Mat 转换为 WPF BitmapSource
///
private static BitmapSource MatToBitmapSource(Mat mat)
{
int width = mat.Width;
int height = mat.Height;
int channels = mat.NumberOfChannels;
int stride = mat.Step;
byte[] pixels = new byte[height * stride];
Marshal.Copy(mat.DataPointer, pixels, 0, pixels.Length);
var format = channels == 3 ? PixelFormats.Bgr24 : PixelFormats.Gray8;
return BitmapSource.Create(width, height, 96, 96, format, null, pixels, stride);
}
}
}