C# .NET中不使用GDI+实现Skia(Sharp)与OpenCV(Emgu)图像传递
在C# .NET中SkiaSharp与Emgu CV无GDI+的图像传递方案
一、SkiaSharp Bitmap 转 Emgu CV Mat
直接操作SkiaSharp的像素缓冲区,结合Emgu CV的Mat结构实现转换,核心是匹配通道顺序(Skia默认RGBA,Emgu常用BGR/BGRA)。
using SkiaSharp; using Emgu.CV; using Emgu.CV.CvEnum; public static Mat SkiaBitmapToEmguMat(SKBitmap skBitmap) { skBitmap.LockPixels(); try { // 创建临时Mat存储RGBA原始数据 var tempRgbaMat = new Mat(skBitmap.Height, skBitmap.Width, DepthType.Cv8U, 4); // 复制像素内存 System.Runtime.InteropServices.Marshal.Copy( skBitmap.GetPixels(), tempRgbaMat.DataPointer, 0, skBitmap.RowBytes * skBitmap.Height ); // 转换为Emgu常用的BGR格式(无Alpha) var bgrMat = new Mat(); CvInvoke.CvtColor(tempRgbaMat, bgrMat, ColorConversion.Rgba2Bgr); tempRgbaMat.Dispose(); return bgrMat; // 若需保留Alpha通道,替换为以下代码: // var bgraMat = new Mat(); // CvInvoke.CvtColor(tempRgbaMat, bgraMat, ColorConversion.Rgba2Bgra); // tempRgbaMat.Dispose(); // return bgraMat; } finally { skBitmap.UnlockPixels(); } }
二、Emgu CV Mat 转 SkiaSharp Bitmap
将Emgu的Mat像素数据转换为Skia支持的RGBA格式,直接写入SkiaBitmap的内存缓冲区。
using SkiaSharp; using Emgu.CV; using Emgu.CV.CvEnum; public static SKBitmap EmguMatToSkiaBitmap(Mat emguMat) { SKBitmap skBitmap = null; Mat tempRgbaMat = null; try { // 转换Mat为RGBA格式 if (emguMat.NumberOfChannels == 3) { tempRgbaMat = new Mat(); CvInvoke.CvtColor(emguMat, tempRgbaMat, ColorConversion.Bgr2Rgba); } else if (emguMat.NumberOfChannels == 4) { tempRgbaMat = new Mat(); CvInvoke.CvtColor(emguMat, tempRgbaMat, ColorConversion.Bgra2Rgba); } else { throw new ArgumentException("仅支持3通道BGR或4通道BGRA格式的Mat"); } // 创建匹配尺寸和格式的SkiaBitmap skBitmap = new SKBitmap( tempRgbaMat.Width, tempRgbaMat.Height, SKColorType.Rgba8888, SKAlphaType.Unpremul ); skBitmap.LockPixels(); try { // 复制转换后的像素数据 System.Runtime.InteropServices.Marshal.Copy( tempRgbaMat.DataPointer, skBitmap.GetPixels(), 0, tempRgbaMat.Rows * tempRgbaMat.Step ); } finally { skBitmap.UnlockPixels(); } return skBitmap; } finally { tempRgbaMat?.Dispose(); } }
关键注意事项
- 通道顺序:Skia默认采用RGBA字节顺序,Emgu CV默认彩色格式为BGR/BGRA,必须通过
CvInvoke.CvtColor转换,否则会出现颜色错乱。 - 内存管理:务必在操作完成后解锁SkiaBitmap的像素缓冲区,及时Dispose临时Mat对象,避免内存泄漏。
- 格式限制:上述代码仅支持8位无符号整数格式(
DepthType.Cv8U),若需处理其他格式(如16位、浮点),需额外添加格式转换逻辑。
内容的提问来源于stack exchange,提问作者SofaKng
相关产品推荐
相关产品推荐

