You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 03:56:11