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

WinUI3中如何将8位灰度原始像素数组(byte[])显示到Image控件

问题:8位灰度像素数组转WriteableBitmap后Image控件无显示

我从相机获取了原始8位灰度像素数组(byte[]),像素格式信息:

  • 8位灰度(颜色通道数=1)
  • 尺寸:宽度612,高度512,总字节数=612×512=313344字节

通过事件将数组通知到主页面后,Image控件始终无法显示内容,以下是我的代码:

主页面后台代码

// This event is called when camera image was captured from camera library
private void Camera_ImageCaptured(object? sender, ImageCapturedEventArgs e)
{
    // CameraImage is Image control of the main page
    _ = CameraImage.DispatcherQueue.TryEnqueue(async () =>
    {
        await GetBitmapAsync3(e.ImageBuffer, e.Width, e.Height);
    });
}

// This method is called in UI thread
public async Task GetBitmapAsync3(byte[] data, int width, int height)
{
    WriteableBitmap newImage = new WriteableBitmap(width, height);
    using var stream = newImage.PixelBuffer.AsStream();
    stream.Write(data);
    await stream.FlushAsync();
    stream.Close();
    ViewModel.WriteableBitmap = newImage;
}

// parameters from camera library
public class ImageCapturedEventArgs : EventArgs
{
    public ImageCapturedEventArgs( byte[] buffer, int width, int height );

    public int Height { get; set; }
    public int Width { get; set; }
    public byte[] ImageBuffer { get; set; }
}

ViewModel代码

public partial class MainViewModel : ObservableRecipient
{
    [ObservableProperty]
    public WriteableBitmap writeableBitmap;
    public int ImageWidth{ get; set; }
    public int ImageHeight { get; set; }
    public int ImageSize => ImageWidth * ImageHeight;

    public MainViewModel()
    {
        ImageWidth = 612;
        ImageHeight = 512;

        writeableBitmap = new WriteableBitmap(ImageWidth, ImageHeight);
    }
}

主页面XAML代码

<UserControl.DataContext>
    <viewmodels:MainViewModel />
</UserControl.DataContext>

<Grid x:Name="ContentArea">
    <Image
        x:Name="CameraImage"
        Grid.Row="0"
        Grid.Column="0"
        Width="612"
        Height="512"
        Source="{Binding WriteableBitmap}" />
</Grid>

解决方案

问题核心:WriteableBitmap默认采用BGRA32像素格式(4字节/像素),但你传入的是8位灰度数据(1字节/像素),像素格式不匹配导致无法正确渲染。

需要将单通道灰度数据转换为BGRA32格式,每个灰度值对应B、G、R三个通道相同的值,A通道设为255(不透明)。修改后的GetBitmapAsync3方法如下:

public async Task GetBitmapAsync3(byte[] data, int width, int height)
{
    // 初始化BGRA32格式的WriteableBitmap,每个像素占4字节
    WriteableBitmap newImage = new WriteableBitmap(width, height);
    
    // 创建BGRA转换后的缓冲区
    byte[] bgraData = new byte[width * height * 4];
    for (int i = 0; i < data.Length; i++)
    {
        // 灰度值赋值给B、G、R通道,A通道设为255
        bgraData[i * 4] = data[i];     // B
        bgraData[i * 4 + 1] = data[i]; // G
        bgraData[i * 4 + 2] = data[i]; // R
        bgraData[i * 4 + 3] = 255;     // A
    }

    // 将转换后的数据写入PixelBuffer
    using var stream = newImage.PixelBuffer.AsStream();
    await stream.WriteAsync(bgraData, 0, bgraData.Length);
    await stream.FlushAsync();
    
    // 强制刷新WriteableBitmap,确保UI感知到像素变化
    newImage.Invalidate();
    
    // 通知UI更新
    ViewModel.WriteableBitmap = newImage;
}

额外注意事项:

  1. 补全ImageCapturedEventArgs的构造函数,确保属性正确初始化:
public ImageCapturedEventArgs(byte[] buffer, int width, int height)
{
    ImageBuffer = buffer;
    Width = width;
    Height = height;
}
  1. 确认主页面与ViewModel的绑定关系正常,避免出现绑定失效问题。

内容的提问来源于stack exchange,提问作者Ken

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 12:59:20