MAUI中如何将YUV/RGB格式byte[]绘制到视图?
在MAUI中绘制YUV/RGB格式的byte[]到视图
要直接绘制YUV/RGB格式的byte[]到MAUI视图,你可以基于SkiaSharp和Microsoft.Maui.Graphics.Skia实现,核心思路是通过SKBitmap直接操作像素缓冲区,再将其转换为MAUI Graphics可用的IImage,并确保帧更新后触发视图重绘。
你的代码存在的关键问题
SkiaImage基于SKBitmap创建后,SKBitmap的像素更新不会自动同步到SkiaImage,导致绘制的始终是初始帧- 未在帧更新后触发
GraphicsView的重绘操作,新帧无法显示 - 像素格式可能不匹配(比如你用了
Rgb888x但转成了RGBA数据)
修正后的实现代码
using Microsoft.Maui.Graphics.Skia; using SkiaSharp; namespace MauiSample { internal class VideoDrawable : IDrawable, IDisposable { private SKBitmap? _skBitmap; private IImage? _mauiImage; private uint _currentWidth; private uint _currentHeight; private readonly GraphicsView _graphicsView; // 传入关联的GraphicsView,用于触发重绘 public VideoDrawable(GraphicsView graphicsView) { _graphicsView = graphicsView; } public void Draw(ICanvas canvas, RectF dirtyRect) { if (_mauiImage == null) return; // 按视图尺寸缩放绘制 canvas.DrawImage(_mauiImage, 0, 0, dirtyRect.Width, dirtyRect.Height); } private void EnsureBitmap(uint width, uint height) { if (_currentWidth == width && _currentHeight == height && _skBitmap != null) return; _currentWidth = width; _currentHeight = height; // 释放旧资源 _skBitmap?.Dispose(); _mauiImage?.Dispose(); // 创建匹配RGBA8888格式的Bitmap(对应YUV转RGBA后的4字节像素) _skBitmap = new SKBitmap((int)width, (int)height, SKColorType.Rgba8888, SKAlphaType.Premul); _mauiImage = new SkiaImage(_skBitmap); } public void UpdateVideoFrame(byte[] yuvFrame, uint width, uint height) { EnsureBitmap(width, height); if (_skBitmap == null) return; // 将YUV转换为RGBA像素 byte[] rgbaPixels = new byte[width * height * 4]; VideoFrameConverter.YUV2RGBA(yuvFrame, rgbaPixels, width, height); // 将像素数据写入SKBitmap unsafe { fixed (byte* ptr = rgbaPixels) { _skBitmap.SetPixels((nint)ptr); } } // 触发GraphicsView重绘,显示新帧 _graphicsView.Invalidate(); } #region IDisposable实现 private bool _disposed; ~VideoDrawable() => Dispose(false); public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (_disposed) return; if (disposing) { _skBitmap?.Dispose(); _mauiImage?.Dispose(); } _disposed = true; } #endregion } }
使用方式
在你的MAUI页面中:
- 添加
GraphicsView控件:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="MauiSample.VideoPage"> <GraphicsView x:Name="VideoGraphicsView" /> </ContentPage>
- 在后台代码中初始化Drawable并绑定:
public VideoPage() { InitializeComponent(); var videoDrawable = new VideoDrawable(VideoGraphicsView); VideoGraphicsView.Drawable = videoDrawable; // 假设你从某个回调中获取YUV帧数据 // 示例:当收到帧时调用 // videoDrawable.UpdateVideoFrame(yuvFrameData, frameWidth, frameHeight); }
注意事项
- 确保
VideoFrameConverter.YUV2RGBA方法输出的像素格式与SKBitmap创建时的SKColorType.Rgba8888完全匹配,否则会出现画面失真或乱码 - 频繁更新帧时,建议在后台线程处理YUV转RGBA的操作,避免阻塞UI线程
- 对于不同的YUV格式(如NV12、YUV420P等),需要确保转换逻辑正确对应
内容的提问来源于stack exchange,提问作者Cade Huang
相关产品推荐
相关产品推荐

